Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中的宏中声明变量,允许尾随分号_C_Macros - Fatal编程技术网

在C中的宏中声明变量,允许尾随分号

在C中的宏中声明变量,允许尾随分号,c,macros,C,Macros,对于宏声明来说,这是一个愚蠢的问题,但我已经遇到过好几次了,我很好奇是否有我遗漏的解决方案 我有一个声明变量的宏,我想确保这些变量没有被错误初始化 #define DECLARE_FOO(var) \ int _##var##_a = 0; \ int _##var##_b = 0 示例用法: DECLARE_FOO(var); 然而这允许 DECLARE_FOO(var) + 1; 我可以暂时忽略这一点,但我不允许这样做。简单的 #define DECLARE_FOO(v

对于宏声明来说,这是一个愚蠢的问题,但我已经遇到过好几次了,我很好奇是否有我遗漏的解决方案

我有一个声明变量的宏,我想确保这些变量没有被错误初始化

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0
示例用法:

DECLARE_FOO(var);
然而这允许

DECLARE_FOO(var) + 1;
我可以暂时忽略这一点,但我不允许这样做。简单的

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0;
但是,现在我必须从声明中删除分号,否则我将收到此警告

DECLARE_FOO(var);
int bar;
ISO C90禁止混合声明和代码[-Werror=声明后声明]

所以,我必须这样做

DECLARE_FOO(var)
int bar;
…它正确展开,但对于阅读代码而不检查宏定义的人来说,它看起来很奇怪。另外,不展开宏的编辑器可能会因为语法不正确而发出警告

是否有某种方法可以禁止对变量赋值,但也可以使用分号结束声明的使用

使现代化
我的问题不是很清楚,但是-Werror=语句后声明推断C90是这里的一个要求,在这种情况下,混合语句的答案不起作用,因为可能会有继续声明。

在宏中添加一个无操作表达式:

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    (void) 0
顺便说一句:如果使用宏时没有分号,这甚至会失败

更新:另一个技巧:使宏的最后一行成为一个外部声明,它也是一个no-op,但是没有分号会阻塞

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    extern int _##var##_ext

将无操作表达式添加到宏:

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    (void) 0
顺便说一句:如果使用宏时没有分号,这甚至会失败

更新:另一个技巧:使宏的最后一行成为一个外部声明,它也是一个no-op,但是没有分号会阻塞

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    extern int _##var##_ext

只要C90不允许混合减速和语句,就不可能防止宏后面出现拖尾文本

但是,可以使用三元运算符忽略尾随文本,这是一个相当糟糕的解决方案,我不建议使用它

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 1 ? 0 : 0
这不会引发错误,但+1将被忽略

DECLARE_FOO(var) + 1;

只要C90不允许混合减速和语句,就不可能防止宏后面出现拖尾文本

但是,可以使用三元运算符忽略尾随文本,这是一个相当糟糕的解决方案,我不建议使用它

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 1 ? 0 : 0
这不会引发错误,但+1将被忽略

DECLARE_FOO(var) + 1;

为什么你还在按照C90标准编程?自1999年以来,我们可以在C语言中混合使用代码和声明。因此,只要切换到更现代的方言,编译器就会忽略双分号。@cmaster,因为它与MSVC2008兼容,仍然禁止混合声明和代码。尽管我在Linux上使用GCC4.8和Clang,但为什么您仍在使用C90标准编程?自1999年以来,我们可以在C语言中混合使用代码和声明。因此,只要切换到更现代的方言,编译器就会忽略双分号。@cmaster,因为它与MSVC2008兼容,仍然禁止混合声明和代码。尽管我在LinuxIt上使用GCC4.8和Clang,这会给出警告/错误,但ISO C90禁止混合声明和代码,前提是您连续两次调用macto。c99确实允许混合代码和声明。不只是在一行中调用两次,而是在它之后定义任何变量,这使得它非常有限。是的,我知道。关于外部使用的发现很好!,虽然后来在名称空间中出现了一个虚拟变量,但我现在从GCC得到一个警告,它未使用,这可能仍然是迄今为止最接近答案的一个。这给出了警告/错误,ISO C90禁止混合声明和代码,仅当您连续两次调用macto时。c99确实允许混合代码和声明。不只是在一行中调用两次,而是在它之后定义任何变量,这使得它非常有限。是的,我知道。关于外部使用的发现很好!,虽然最后在名称空间中出现了一个虚拟变量,我现在从GCC得到一个警告,它未被使用,但它可能仍然是迄今为止最接近答案的东西。