英文:
Are _Pragma operators allowed in the middle of function prototype declarations?
问题
I've encountered some code like this:
void _Pragma("function") f() {
int i = 0;
_Pragma("loop");
while (i < 100) {
...
}
}
GCC编译这段代码时没有问题。但我不确定标准中具体允许_Pragma
出现在这种位置,特别是在void
和f()
之间。
我的C11标准版本(N1570)中写道:
6.10.9 Pragma operator
Semantics
A unary operator expression of the form:
_Pragma ( string-literal )
...
给出的示例几乎与#pragma
相同,这意味着它应该单独占据一行。
第6.5.3节 一元操作符 甚至没有提到_Pragma
。
在语法规则中,我找不到允许一元操作符出现在void
和f()
之间的位置。
GCC文档只是声称:
标准对
_Pragma
操作符的出现位置没有明确规定。
我认为除非明确在语法上允许,否则应该禁止在不明确规定的位置使用_Pragma
。这是否未指定或由实现定义允许_Pragma
出现在这些位置呢?
英文:
I've encountered some code like this:
void _Pragma("function") f() {
int i = 0;
_Pragma("loop");
while (i < 100) {
...
}
}
GCC compiles it without issues. But I don't see exactly where in the standard it allows _Pragma
's to appear in such positions, especially between the void
and f()
.
My version of the C11 standard (N1570) states:
> 6.10.9 Pragma operator
>
> Semantics
>
> A unary operator expression of the form:
>
> _Pragma ( string-literal )
> ...
The example given behaves almost as #pragma
, which means, on a line by its own.
Section 6.5.3. Unary operators does not even mention _Pragma
.
I fail to see in the syntactic rules where unary operators would be allowed in the position between void
and f()
.
The GCC docs just claim that:
> The standard is unclear on where a _Pragma
operator can appear.
I would assume that it is forbidden anywhere where not syntactically explicitly allowed.
Is it unspecifed, or implementation-defined, to allow such occurrences of _Pragma
?
答案1
得分: 3
_Pragma
的主要目的是允许你在预处理#define
宏内部使用编译指示。对于其他目的使用它通常没有意义。
此外,6.10.9 规定:
> 生成的字符序列经过第三个转换阶段处理,生成处理预处理令牌,它们被执行,就好像它们是#pragma
指令中的pp-token。
你可以解释为:应该单独写在一行上,因为#pragma
- 作为预处理指令 - 就是这样工作的。在这种情况下,因为诸如void #pragma function
这样的代码是无效的,对于_Pragma
来说也是一样的。
引用你找到的gcc文档:
> 为了安全起见,最好将其放在除了#define之外的指令之外,并将其放在独立的一行上。
此外,一般的最佳实践是:
- 不要随意编写奇怪的代码。
- 不要仅仅为了某种目的而使用奇怪的编译器扩展。
尽管编译器应该忽略未识别的编译指示,这似乎是gcc、clang等编译器正在做的。如果你使用严格的设置编译(-std=c17 -pedantic -Wall -Wextra
),它们会发出警告然后忽略它。
英文:
_Pragma
pretty much have one single purpose: to allow you to use pragmas inside pre-processor #define
macros. It isn't (shouldn't be) meaningful to use it for any other purpose.
Other than that, 6.10.9 says:
> The resulting sequence of characters is processed through translation phase 3 to produce preprocessing tokens that are executed as if they were the pp-tokens in a pragma directive.
You could interpret this as: meant to be written on a line of its own, since #pragma
- being a pre-processor directive - works that way. In that case, since code such as void #pragma function
is invalid, the same should go for _Pragma
.
To quote the gcc doc you found:
> To be safe, you are probably best keeping it out of directives other than #define, and putting it on a line of its own.
In addition, general best practices are:
- Don't write strange code just for the heck of it.
- Don't use weird compiler extensions just for the heck of it.
Although compilers should ignore unrecognized pragmas and that seems to be what gcc, clang et al are doing. Neither "compiles it without any issues" if you compile with strict settings -std=c17 -pedantic -Wall -Wextra
, they warn and then ignore it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论