您尝试使用众所周知的 C 预处理器字符串化配方,
即:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
失败有两个原因,每个原因本身就足够了。
首先也是最简单的,您显然尝试在其中使用它的源文件
有扩展名.f90
。此扩展名的含义是什么gfortran
(并
GCC 编译器驱动程序(任何其他名称)是:不应进行预处理的自由格式 Fortran 源代码。相似地.f95
, .f03
and .f08
。如果你想gfortran
推断出一个来源
文件包含自由格式的 Fortran 代码must进行预处理,给它之一
扩展.F90
, .F95
, .F03
or .F08
. See GCC 文档
这几点 https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options
然而,即使你做了那么简单的事情,第二个原因也很重要。
使用 C 预处理器来预处理 Fortran 源代码与 C 一样古老
(虽然很老,但比 Fortran 年轻得多)。gfortran
有义务不
打破古老的工作密码;因此,当它调用 C 预处理器时,
它在中调用它传统模式. The 传统模式C 预处理器的
是预处理器在第一次标准化之前的行为方式
C 语言(1989),只要非标准化行为可以被确定。在传统的
模式下,预处理器无法识别字符串化运算符“#”,这是
由第一个 C 标准引入。您可以通过调用预处理器来验证这一点
直接喜欢:
cpp -traditional test.c
where test.c
包含一些使用字符串化方法的尝试。这
尝试失败。
你不能哄gfortran
独自工作字符串化配方。
但有一个解决方法。您可以调用cpp
直接,不受传统模式的束缚,
预处理要在其中完成字符串化的 Fortran 源代码并中继其
输出到gfortran
。如果您已经知道这一点并且正在寻找gfortran
-独自的
您无需进一步阅读解决方案。
以这种方式在测试源中进行字符串化将如下所示:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' '-DMYMACRO=STRINGIFY(hello)' test.f90
其输出是:
# 1 "test.f90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.f90"
program test
implicit none
character (len=:), allocatable :: astring
astring = "hello"
write (*, *) astring
end program test
该输出就是您想要编译的内容。您也可以通过以下方式实现这一点:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 > /tmp/test.f90 \
&& gfortran -o test /tmp/test.f90
然后你会发现./test
存在并且执行它输出hello
.
您可以通过进一步细化消除中间临时文件。您的 F90 来源
代码将编译为 F95,因为后者比前者保守。所以你可以采取
这样做的好处是,如果
你告诉它你正在管道的语言,使用它-x
language选项。这
您可以通过这种方式指定的 Fortran 方言是f77
, f77-cpp-input
, f95
and f95-cpp-input
,其中-cpp-input
前缀表示
源将被预处理,它的缺失表示它没有被预处理。因此
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 | gfortran -x f95 -o test -
与之前的解决方案一样工作,减去临时文件,并发出
无害的警告:
Warning: Reading file '<stdin>' as free form
(注意并保留最后的 -
在命令行上。这就是告诉我们的gfortran
到
编译标准输入。)。的含义-x f95
带来了额外的
经预处理的经济来源cpp
, 没有经过预处理
再次由编译器执行。
选项的使用-std=c89
当调用cpp
呼吁警惕
解释。它具有使cpp
符合最早的C标准。
那是接近-traditional
我们可以在仍然利用的同时得到#
- 运算符,字符串化配方取决于它,但有了它你就可以拥抱
打破的可能性someFortran 代码(如果您以这种方式预处理它);
否则gfortran
本身不会强制执行-traditional
。如果是
你的测试程序,你可以安全地省略-std=c89
,允许cpp
来确认
构建时遵循默认的 C 标准。但如果你允许或指示它
符合-std=c99
或稍后,标准将强制认可
的//
作为单行注释的开头(按照 C++),其中任何行
包含串联运算符的 Fortran 语言将在
第一次出现。
当然,如果您使用 are usingmake
或另一个构建系统来构建
您想要字符串化宏的代码,您将有一种方法来告诉
构建系统什么动作构成编译给定的可编译类
文件。对于任何 Fortran 源文件fsrc
你想编译
字符串化序言,指定的操作将是这样的:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' fsrc.f90 | gfortran -x f95 -c -o fsrc.o -