【问题标题】:C Error checking macro definition with function call as argument won't compile on MSVC使用函数调用作为参数的 C 错误检查宏定义不会在 MSVC 上编译
【发布时间】:2015-11-28 01:19:52
【问题描述】:

我正在尝试使用一些针对 Windows 上的 C99 的代码(MSVC、C11)。这是一些用于 OpenCL 调用的调试宏:

#define CL_CHECK(_expr)                                                         \
   do {                                                                         \
     cl_int _err = _expr;                                                       \
     if (_err == CL_SUCCESS)                                                    \
       break;                                                                   \
     fprintf(stderr, "OpenCL Error: '%s' returned %d!\n", #_expr, (int)_err);   \
     abort();                                                                   \
   } while (0)

#define CL_CHECK_ERR(_expr)                                                     \
   ({                                                                           \
     cl_int _err = CL_INVALID_VALUE;                                            \
     typeof(_expr) _ret = _expr;                                                \
     if (_err != CL_SUCCESS) {                                                  \
       fprintf(stderr, "OpenCL Error: '%s' returned %d!\n", #_expr, (int)_err); \
       abort();                                                                 \
     }                                                                          \
     _ret;                                                                      \
   })

当 _expr 的返回类型已知为 cl_int 类型时,使用第一个。第二个可以是任何类型,这就是我遇到编译问题的地方。我将 typeof(_expr) 替换为“auto”,但编译器一直在抱怨:

  Error 8   IntelliSense: expected an expression    d:\work\Labs\dagSimCL\dagSimCL.cpp  136 23  dagSimCL
  Error 6   error C2143: syntax error : missing ';' before '{'  D:\work\Labs\dagSimCL\dagSimCL.cpp  136 1   dagSimCL
Error   7   error C2143: syntax error : missing ';' before ')'  D:\work\Labs\dagSimCL\dagSimCL.cpp  136 1   dagSimCL
Error   5   error C2059: syntax error : '{' D:\work\Labs\dagSimCL\dagSimCL.cpp  136 1   dagSimCL    

我向宏扔什么并不重要,它总是一样的。但作为参考,这就是我正在做的事情:

cl_context context = CL_CHECK_ERR(clCreateContext(contextProperties, 1, &devices[device_id], NULL, NULL, &_err));

奇怪的是,当我尝试将代码包装在 do/while 中而不是像第一个宏中的 () 时,它开始抱怨“do”。我在这里有点不知所措。我可以忘记它并跳过错误检查,但我想了解发生了什么问题......

【问题讨论】:

  • 你不需要 ; while(0) 之后?
  • 通常不会@SnakeSanders。当您使用宏时添加半,例如CL_CHECK_ERR(expr) ;
  • @Snake Sanders:do/while 语句是确保宏扩展为单个语句的技巧。假设; 出现在宏调用之后并充当单个语句终止。
  • @JJF: CL_CHECK(expr); 在这种情况下。 CL_CHECK_ERR(expr) 应该用在表达式上下文中,例如return CL_CHECK_ERR(expr);
  • AFAIK,typeof 是 gcc 扩展,“comund statement as an expression”构造也是 gcc 扩展,auto 类型说明符是 C++ 特性(它是 C 中的存储类),并且 MSVC 从未符合 C99。

标签: c visual-c++ macros opencl


【解决方案1】:

CL_CHECK_EXPR() 宏对我来说似乎不正确:

  • _err 上的测试应该总是失败,因为 CL_INVALID_VALUE 应该不同于 CL_SUCCESS

  • 我想_err 应该是从_expr 派生的,但正如它所写的那样,它不起作用。

  • 解决typeof 缺乏可移植性的简单方法是将实际类型作为宏参数传递。 C 不支持在 C++ 中使用 auto 关键字推断类型。

  • 此外,您的编译器可能不支持表达式语句扩展,因此您几乎没有其他选择。

您可能应该更改要包装在此类宏中的内部 API,以始终返回错误代码并使用指针参数返回正常结果。

【讨论】:

  • _err_expr 中的函数调用填充。请参阅问题中的最后一个代码 sn-p。
  • 我明白了,这是一个非常丑陋的副作用。您绝对应该将状态返回变量的名称作为宏参数传递。
  • 恐怕将表达式的类型作为额外的宏参数传递似乎是 C 的唯一解决方案
  • 如果是 C++11?
【解决方案2】:

CL_CHECK_EXPR() 不是有效的 C 表达式,也不是用于赋值运算符右侧的初始化列表:

cl_context context = CL_CHECK_EXPR(...);

C 中的表达式不能包含复合语句(即{ })、if 语句或声明语句等语句。

您确实需要将这些内容放在返回所需表达式的函数中,并让CL_CHECK_EXPR() 宏调用该函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2015-02-11
    • 2021-10-12
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 2013-09-29
    相关资源
    最近更新 更多