__FILE__在.h文件中是什么意思?

14

如果__FILE__宏在一个.h文件中,有没有规定它会被如何展开?

如果我在foo.h中定义:

#define MYFILE __FILE__

并将其包含在foo.c

#include "foo.h"

int main(){
  printf("%s",MYFILE);
  ....
}

这段代码会输出foo.h还是foo.c?(我知道这个例子很愚蠢)

抱歉问一个简单的问题。网上的文档似乎存在冲突。值得一提的是,VS2008会返回foo.c,这也是我所期望的……我想确认这是否是定义行为。


4
原帖作者已经尝试过这个方法,他想知道这种行为是否被定义并且具有可移植性。 - yan
感谢大家的回答……我想我只是太狭隘地只想在规范中寻找__FILE__……但从一个通用的宏的角度来看,这就很合理了。 - Pablitorun
5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
10

yan答案 中给出的建议“通常是正确的”。也就是说,当宏被使用时,__FILE__ 的值是当前源文件的名称,而不是宏定义时的名称。但是,这并不是绝对正确的 - 这里有一个反例:

$ cat x.h
static void helper(void)
{
    printf("%s:%d helper\n", __FILE__, __LINE__);
}
$ cat x.c
#include <stdio.h>
#include "x.h"

int main(void)
{
    helper();
    printf("%s:%d\n", __FILE__, __LINE__);
    return 0;
}

$ make x
cc -Wall -Wextra -std=c99 -g x.c -o x
$ ./x
x.h:3 helper
x.c:7
$

这是一个人为制造的例子;在 C 语言中,你很少会像我在这里那样把实际的代码放到头文件里 —— 除非你使用 inline 函数。但输出结果表明,在某些情况下,头文件名可以成为 __FILE__ 展开后的正确名称。


实际上,在头文件中放置内联函数是很常见的,所以这并不是非常牵强。对于这个好观点加一分。 - Jim Balter
@Jim:你说得对——如果允许使用 C99 的那个特性的话。由于(据我所知)MSVC 不支持 C 编译中的内联函数(当然,C++ 是另一回事),所以我们不能使用内联函数。(虽然我从 MSDN 看到 MSVC 允许使用 __inline……嗯,也许还有希望。) - Jonathan Leffler
C99标准十年前就被采纳了。我很高兴不必使用这样错误的工具进行开发。 - Jim Balter
@Jim:告诉我关于它的事情。当然,人们可以问它是何时被实现的,而不是被采用的。你也可以争辩说微软从未采用过它。此外,我担心下一个C1X标准将是一个更弱的标准;如果你需要知道我在说什么,请参阅comp.std.c上的讨论。 - Jonathan Leffler

10

在使用__LINE____FILE__ 之后,它将始终返回使用它的.c文件。这是因为预处理器会解析__LINE____FILE__ 。您可以编写使用__FILE____LINE__ 的调试宏,并使它们指向调试语句所在的位置。


Jonathan Leffler在他的回答中提出了一个很好的观点...如果使用__LINE__或__FILE__的代码位于头文件中,则会打印头文件的名称。例如,在头文件中定义内联函数时就是这种情况。 - Jim Balter
2
我对“__LINE____FILE__在预处理器之后被解析”的说法有问题。它们是由预处理器解析的,编译器本身看不到下划线符号。 - Jonathan Leffler

5

宏展开(包括所有宏,而不仅仅是像__FILE__这样的特殊宏)在#include替换之后进行,因此可以依靠这种行为。


4

标准中的实际语言是(§6.10.8):

__FILE__ 当前源文件的预设名称(一个字符字符串字面量)。

由于宏展开发生在处理 #include 之后,因此“当前源文件”是正在被编译的预处理 .c 文件。


标准规定:“#include 预处理指令会导致命名的头文件或源文件从第一阶段到第四阶段递归地被处理。”因此,在宏展开(第四阶段)时,预处理器知道正在处理的是特定的头文件是完全可能的(甚至可能是必需的)。同时请注意,“当前源文件的假定名称”可以通过 #line 指令进行修改。 - Michael Burr

3

那个#define宏在预编译时进行文字替换。当C编译器处理foo.c文件时,它会看到:

printf("%s", __FILE__);

所以你要获取foo.c文件。


实际上,编译器本身看到的是printf("%s","foo.c");; __FILE__是由预处理器定义和展开的宏。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,