c - 宏扩展中 OpenMP Pragma 的错误替换

标签 c gcc macros openmp variadic-macros

当 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/

相关文章:

c - 扩展哈希表而不重新哈希?

c - 如何检查存储在变量中的给定文件描述符是否仍然有效?

c - 从一个简单的网页在 C 程序中设置变量

c++ - 如何把一个系统环境变量作为一个宏定义到一个C头文件中?

macros - 如果 Lisp 中的宏是一元的,这意味着什么?

c++ - C++ 中的宏会提高性能吗?

c - 尝试访问二进制文件时出现段错误

c++ - 强制结构大小为 8 字节

c - Printf 和 fprintf 只打印第一个参数

c - 为什么 scanf_s 在 vi​​sual studio 以外的地方不起作用?