【问题标题】:__FILE__ In .h what does it resolve to__FILE__ 在 .h 中它解析为什么
【发布时间】:2023-03-26 22:43:02
【问题描述】:

如果__FILE__ 宏位于.h 中,是否有关于如何扩展它的规范?

如果我在foo.h中定义

#define MYFILE __FILE__

并将其包含在foo.c

#include "foo.h"

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

这个输出是foo.h 还是foo.c? (是的,我知道这是一个愚蠢的例子)

很抱歉应该是一个简单的问题。网络上的文档似乎相互矛盾。对于它的价值,VS2008 以foo.c 的形式返回,这是我所期望的......我想。我只是想确认这是否是已定义的行为。

【问题讨论】:

  • 原发帖人确实尝试过,他在询问该行为是否已定义且可移植。
  • 谢谢大家的回答......我想我想得太狭隘了,只考虑查看 FILE 的规范......当被视为通用宏,它非常有意义。

标签: c macros c-preprocessor


【解决方案1】:

yananswer 中给出的建议“通常是正确的”。即__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__ 扩展为的正确名称。

【讨论】:

  • 实际上,将内联函数放在头文件中是很常见的,所以这并不是那么做作。 +1 好点。
  • @Jim:你是对的——如果你被允许使用 C99 的那个特性的话。由于(AFAIK)MSVC 不支持 C 编译的内联函数(当然,C++ 是另一回事),我们不允许使用内联函数。 (虽然我从 MSDN 看到 MSVC 允许 __inline...hmmm,也许还有希望。)
  • C99 标准是十多年前采用的。我很高兴我不必使用这些损坏的工具进行开发。
  • @Jim:告诉我吧。当然,人们可以问它何时实施——而不是采用。您也可以争辩说 MS 从未采用过它。另外,我担心下一个 C1X 标准将是一个弱得多的标准;如果您想知道我在说什么,请参阅 comp.std.c 上的讨论。
【解决方案2】:

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

【讨论】:

  • Jonathan Leffler 在他的回答中提出了很好的观点......如果使用 LINEFILE 的代码在头文件中,那么名称打印头文件。例如,头文件中定义的内联函数就是这种情况。
  • 我对“__LINE____FILE__ 在预处理器之后解决”的说法有疑问。它们由预处理器解析;正确的编译器看不到下划线符号。
【解决方案3】:

宏扩展(所有宏,不仅仅是像 __FILE__ 这样的特殊宏)在#include 替换之后完成,所以是的,可以依赖这种行为。

【讨论】:

    【解决方案4】:

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

    __FILE__ 当前源文件的假定名称(字符串文字)。

    因为在处理#includes 之后发生宏扩展,所以“当前源文件”是正在编译的预处理.c 文件。

    【讨论】:

    • 标准规定“#include 预处理指令导致命名的头文件或源文件从阶段 1 到阶段 4 以递归方式进行处理”。因此,预处理器当然有可能(甚至可能需要)知道它是在为其扩展宏(在第 4 阶段)时正在处理的特定头文件。另外请记住,当前源文件的“假定名称”可以通过#line 指令进行修改。
    【解决方案5】:

    #define 宏执行文字文本替换预编译。当 C 编译器访问您的 foo.c 文件时,它会看到:

    printf("%s", __FILE__);
    

    所以你得到了 foo.c.

    【讨论】:

    • 其实编译器看到printf("%s","foo.c");; __FILE__ 是由预处理器定义和扩展的宏。
    猜你喜欢
    • 1970-01-01
    • 2013-07-07
    • 2022-10-05
    • 2015-12-17
    • 2014-09-28
    • 1970-01-01
    • 2011-07-06
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多