C 预处理无法在 #error 后立即停止

标签 c gcc compilation c-preprocessor avx

我今天的问题应该不是很复杂,但我就是找不到原因/解决方案。作为一个可重现的小例子,请考虑以下玩具 C 代码

#define _state_ 0

#if _state_ == 1
int foo(void) {return 1;}
#else

/* check GCC flags first
   note that -mfma will automatically turn on -mavx, as shown by [gcc -mfma -dM -E - < /dev/null | egrep "SSE|AVX|FMA"]
   so it is sufficient to check for -mfma only */

#ifndef __FMA__
#error "Please turn on GCC flag: -mfma"
#endif

#include <immintrin.h>  /* All OK, compile C code */
void foo (double *A, double *B) {
  __m256d A1_vec = _mm256_load_pd(A);
  __m256d B_vec = _mm256_broadcast_sd(B);
  __m256d C1_vec = A1_vec * B_vec;
  }
#endif

我要编译这个test.c文件

gcc -fpic -O2 -c test.c

请注意,我没有打开 GCcflags -mfma,因此将触发 #error。我期望的是,在 GCC 看到此 #error 后,编译将立即停止,但这是我在 GCC 5.3 中得到的结果:

test.c:14:2: error: #error "Please turn on GCC flag: -mfma"
 #error "Please turn on GCC flag: -mfma"
  ^
test.c: In function ‘foo’:
test.c:22:11: warning: AVX vector return without AVX enabled changes the ABI [-Wpsabi]
   __m256d A1_vec = _mm256_load_pd(A);
           ^

GCC 确实停止了,但为什么它还在 #error 之后选择了一行?有什么解释吗?谢谢。


对于想要尝试的人来说,有一些硬件要求。您需要带有 AVX FMA 指令集的 x86-64。

最佳答案

我有一份 C ISO 规范的草稿副本,在 §4/4 中 - 它指出

The implementation shall not successfully translate a preprocessing translation unit containing a #error preprocessing directive unless it is part of a group skipped by conditional inclusion.

稍后,在 §6.10.5 中,#error 被正式定义,它说

A preprocessing directive of the form # error pp-tokens opt new-line causes the implementation to produce a diagnostic message that includes the specified sequence of preprocessing tokens.

换句话说,规范只要求任何有#error的代码只需要在编译过程中失败并报告错误消息,而不是编译需要立即终止,因为一旦到达#error

鉴于始终在编译器报告的顶级错误之前检查顶级错误被认为是一种很好的做法,我可以想象一个称职的程序员看到一串以 #error 开头的错误指令可能知道发生了什么。

关于C 预处理无法在 #error 后立即停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36463958/

相关文章:

c - 使用 RDTSC 测量时差 - 结果太大

c - FIFO 读入 c 得到段错误

c++ - gcc-4.8无法编译测试程序?

c - log(10.0) 可以编译但 log(0.0) 不能使用 undefined reference ?

ios - 编译后包含在我的 xcode 项目中的 plist 有多安全?

c - 在 C 编程中,如何将两个头文件和 3 个 c 文件链接到一个可执行文件中?

c - cURL 选项参数的生命周期是多少?

c - 与 ANSI C 的数据库连接——这可能吗?如何实现?

c - 如何获得有关分配给但不再使用的变量的警告?

c - 编译时出错 - 初始化程序中指定的未知字段