【问题标题】:Can the pre-processor directives like #include be placed only at the top of the program code?像#include 这样的预处理器指令可以只放在程序代码的顶部吗?
【发布时间】:2013-04-29 15:22:30
【问题描述】:

我在函数内部使用了#pragma 指令,没有错误或警告(尤其是#pragma pack())。但以下代码显示警告incompatible implicit declaration of built-in function 'printf'|

int main(void)
{
    printf("Trial");
}

#include<stdio.h>

此外,这是我的一本书的摘录。作者对 SO 的评价很差,尤其是他慷慨地使用了void main(),但我仍然觉得没有一个作者可以那么糟糕无故声称以下内容:

每个预处理器指令都以 # 开头 象征。指令可以放在程序中的任何位置,但 最常放置在程序的开头,在 第一个函数定义。

那么你能告诉我是否必须在程序顶部使用一些预处理器指令,如#include,而其他如#pragma 可以在程序中的任何位置使用?

编辑OUAH的评论之后我尝试了以下,但它没有给出警告,它给出了一大堆错误 .LOL.

int main(void)
{
    #include<stdio.h>
    printf("Trial");
}

【问题讨论】:

  • #include 用于标准头文件的指令只能包含在文件范围内——而不是函数内。 ISO/IEC 9899:2011 §7.1.2 标准标题,¶4 ... 如果使用,标题应包含在任何外部声明或定义之外,并且应首先包含在第一次引用它声明的任何函数或对象,或者它定义的任何类型或宏之前。 ...请注意,此限制仅适用于标准头文件;你可以编写自己的标题,可以放在任何地方(如果你小心的话)。
  • @JonathanLeffler 谢谢,有帮助。

标签: c include c-preprocessor pragma preprocessor-directive


【解决方案1】:

#include 指令可以放置在源文件中的任何位置,但在 C 中,标识符在声明之前通常不能使用。这就是为什么将#include 指令放在源文件开头的原因。

void foo(void)
{
    printf("Hello world\n");
}

extern int printf(const char *, ...);  // Error, the declaration should be put 
                                       // before the actual call

【讨论】:

  • 那么在使用printf() 处理警告之前,我们可以在main() 函数中使用#include 吗?可以吗?
  • 看看我的问题的编辑。它会产生一堆错误。
  • 我在使用printf()之前尝试使用#include,但在main(0内部。它给出了一大堆错误。但是如果我以同样的方式使用#pragma,它不会显示任何警告或错误。为什么?
  • @Rüppell'sVulture 错误与包含指令放在函数中的事实无关,而是因为您应该在文件范围内使用这个特定的头文件。尝试使用一个空的file.h 头文件,您会看到可以将它包含在程序文件的任何位置。
  • @Rüppell'sVulture 自 C99 以来,隐式声明中的规则已被删除。在 C89 中,这也不应该起作用,因为 printf 的隐式声明将是 int printf();,但此声明仅适用于非可变函数。
【解决方案2】:

"#pragma" 指令将被 C 编译器忽略,因为它将带有 "#" 标记的行视为 cmets。看起来你正在使用openmp。 OpenMP 编译器将这些(#pragma) 视为并行指令。希望这会有所帮助。

【讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读FAQ。你说的恐怕完全错了。 ISO/IEC 9899:2011, §6.10.6 Pragma directive# pragma pp-tokens.opt new-line 形式的预处理指令,其中预处理令牌 STDC 不立即遵循 pragma ... 如果预处理令牌 STDC 确实立即遵循 pragma ...
  • @JonathanLeffler 您能否确认乔纳森先生,在没有情况中,编译器会将以# 开头的行视为cmets?
  • @Rüppell'sVulture:我相信说 C 预处理器从不将 # 视为开始评论是正确的。您可以有一个空(null)预处理器指令(# 后跟换行符);你可以有一个预处理器没有注意到的#(有关于预处理器何时检测到#的规则);编译器将忽略它无法识别的指令(任何无法被实现识别的编译指示都会被忽略。)。但我不认为在任何情况下# 符号会引入正式视为评论的内容。
  • 我说的是#pragma 指令。指令遵循编译器指令的 C/C++ 标准约定。用C编译器编译时,它只是一个串行程序,编译器不会抛出任何错误。
【解决方案3】:

这样想。包含文件的内容只是插入到文件中出现#include 指令的位置。生成的代码需要在语法上对于您正在编程的语言是正确的。

请确认以下文件:

int a;

int foo();

int main()
#include "myheader.h"

int foo()
{
    return 0;
}

文件 myheader.h 包含:

{
    return foo();
}

在预处理器处理完#include指令后编译器将看到的代码是:

int a;

int foo();

int main()
{
    return foo();
}

int foo()
{
    return 0;
}

这是有效的 C 语法。不建议使用这种#include 指令,但它可以让您了解它的含义。如果 myheader.h 文件有以下内容:

this is some garbage
which is not proper C

那么生成的代码将是:

int a;

int foo();

int main()
this is some garbage
which is not proper C

int foo()
{
    return 0;
}

您可以在文件中的任何位置使用#include。它会导致在该点上包含包含文件的内容。您在代码中收到 printf() 未声明消息的原因是 C 需要在使用之前声明一个函数,而 stdio.h 具有该声明。这就是为什么它需要在使用之前。而后一个例子中为什么不能将它包含在 main() 中是因为在包含(扩展)时,它会导致语法错误的 C 代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多