我已经编程了C很长一段时间了。在这段时间里,我了解到将#34;#" -character放在第一列的预处理程序指令之前是一种常见的惯例。
示例:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
当人们缩进他们的预处理器指令时,他们通常会这样做:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
# ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
# else
puts("defined(MACRO1)");
# endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我认为我从未见过有人将其格式化为:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我的问题是,C语言标准是否要求#
- 字符应该在第一列。
上面的第三个选项是否合法?
如果以上所有案件都合法,那么我想知道这是否合法。
#include <stdio.h>
int main(void) {
#ifdef MACRO
puts("defined(MACRO)");
/* Now there are other characters before the `#` */ #endif
return 0;
}
以下是#endif
不再在&#34;开始&#34;该行,因为在路上还有其他非空白字符。
最后一个例子看起来很奇怪,Vim
文本编辑器没有突出显示评论后的#endif
。
所有这些示例都是在没有任何警告的情况下使用gcc
打开-Wall -pedantic
标记时进行编译(包括最后一个在#endif
之前发表评论的人)。
请注意,我只是对语法感到好奇。在编程时,我总是将#
- 字符放在第一列,就像其他人一样。我绝不会在严肃的项目中写++i; #endif
之类的东西。
答案 0 :(得分:15)
在一些预标准C预处理器(意思是1989年之前)中,预处理器仅在行的开头识别#
。
由于C89 / C90标准要求预处理器将#
识别为该行上的第一个非空白字符(并且C99和C11标准也是如此),现在缩进指令是完全合法的。甚至便携式代码在这个千年中也是如此。
在ISO / IEC 9899:2011(C11标准)中,第6.10节预处理指令说:
预处理指令由一系列满足以下条件的预处理令牌组成 以下约束:序列中的第一个标记是
#
预处理标记(at 转换阶段4)的开始是源文件中的第一个字符(可选) 在不包含换行符的白色空格之后或在空格之后 包含至少一个换行符。
翻译阶段在第5.1.1.2节翻译阶段中定义。
源文件被分解为预处理令牌7)和序列 空格字符(包括注释)。源文件不得以a结尾 部分预处理令牌或部分注释。每条评论都被替换为 一个空格字符。保留换行符。是否每个都是空的 新行以外的空白字符序列被保留或替换为 一个空格字符是实现定义的。
- 醇>
执行预处理指令,扩展宏调用,以及 _Pragma一元运算符表达式被执行。如果是一个字符序列那个 匹配通用字符名称的语法由token生成 连接(6.10.3.3),行为未定义。
#include
预处理。#
指令导致从阶段1处理命名的头文件或源文件 通过阶段4,递归。然后删除所有预处理指令。
有时候,您会发现源自20世纪80年代的编码标准仍然在行开始时规定了{{1}}。
我通常不会缩进预处理程序指令,但这样做是合法的。
答案 1 :(得分:5)
不,这是C标准的引用(从第6.10节开始):
预处理指令由一系列令人满意的预处理令牌组成 以下约束:序列中的第一个标记是
#
预处理标记(at 转换阶段4)的开始是源文件中的第一个字符(可选地在包含没有换行符的空格之后)或者在空格之后 包含至少一个换行符。
所以它在文件的开头是#
,或者在包含至少一个换行符的某个空格之后。
这意味着:
# define foo
# define bar
foo
的定义很好,因为#
是文件中的第一个标记。 bar
的定义很好,因为#
“跟随包含至少一个换行符的空格。”