当 OpenMP 编译指示用作宏参数的一部分时,它会被错误地替换。 在此代码中:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
我希望它将扩展到:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
但是,(根据 gcc -E)它扩展为:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
这是正确的行为吗? 如何获得预期的行为,最好不更改宏的参数? 所有编译指示都会发生这种情况吗? 这是可变参数宏的效果吗? 其他编译器是否执行相同的替换?
使用gcc(Ubuntu 5.4.0-6ubuntu1~16.04.10)5.4.0 20160609
最佳答案
Is this correct behavior?
最准确的说法是,这是不正确的行为。该标准对宏参数有这样的规定:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
您已经执行了该案例,并相应地收获了未定义的行为。
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
该行为是未定义的,因此它可能会因一致的实现而异,甚至在同一实现内,出于任何原因或没有原因。我猜想 GCC 在这方面是相对一致的,但你绝对不应该依赖它。它与涉及可变参数的宏没有特别关联。
How can I get the expected behavior, preferably without changing the arguments to the macro?
GCC 5 支持的 C11 对于发出编译指示的宏的特定情况有一个解决方案: the _Pragma
operator 。它更常用于文字宏替换文本,因此您可以拥有代表编译指示的宏,但它也应该在宏参数中工作。但是,您必须稍微更改一下宏参数:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
关于c - 宏扩展中 OpenMP Pragma 的错误替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53402468/