标签: variadic-macros

变异的宏伎俩

创建可变参数宏的技巧是什么FOO(a1, a2, a3,..., an),它可以扩展到您选择的任何预选有界范围内的FOOn(a1, a2, a3,..., an)n?也就是说,FOO(a)应该扩展FOO1(a),FOO(a, b, c)FOO3(a, b, c)等,我知道有一个标准的把戏,但我似乎无法找到它.

请随意将此问题标记为副本,如果答案中还有其他问题,请将其关闭.我怀疑有,但我找不到它.

c c-preprocessor variadic-macros

11
推荐指数
3
解决办法
2万
查看次数

清理C/C++代码会显示可变参数宏的问题

我们在C,C++和Java的代码库上进行了一些代码清理,修复了有符号/无符号比较,运行静态分析等.

我们得到的警告之一是

warning: ISO C does not permit named variadic macros
Run Code Online (Sandbox Code Playgroud)

和它的同伴警告

warning: ISO C99 requires rest arguments to be used
Run Code Online (Sandbox Code Playgroud)

现在,在C代码中我使用C99标准可变参数宏来解决问题,但在C++代码中,正确的答案是什么?使用相同的C99样式会产生不同的警告

warning: anonymous variadic macros were introduced in C99 
Run Code Online (Sandbox Code Playgroud)

我没有看到任何答案.

我们在Linux中使用GCC(G ++)4.4.3.

我希望有一些标志或其他方法可以纠正或禁用它的特定代码部分 - 但它用于几乎每个文件中使用的日志...

c c++ macros c99 variadic-macros

11
推荐指数
1
解决办法
8914
查看次数

C中的#define有三个点

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)

这是这两个宏的定义; 在后面的代码LOGI,并LOGW使用这种方式

LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
Run Code Online (Sandbox Code Playgroud)

就这样

LOGW("Unable to eglMakeCurrent");
Run Code Online (Sandbox Code Playgroud)

因为我试图避免复杂的宏,#define一般来说,我无法得到这个宏实际意味着什么.这里的3点符号有什么作用?这#define在代码后面有什么变化?

显然我知道3个点用于表示和无限量的参数,但我不知道如何阅读这种情况.

c label notation c-preprocessor variadic-macros

11
推荐指数
1
解决办法
6847
查看次数

C++预处理器删除对可变参数宏的调用中的空白(Solaris Studio 12.3)

Oracle Solaris Studio 12.3的C++预处理器在扩展时会完全删除空白__VA_ARGS__.

有人可以在他们的系统上确认这种行为吗?它是一个已知的编译器错误吗?这个问题有没有解决方法?

为了说明,这是一个简单的测试程序,vaargs.c:

#include <stdio.h>

#define PRINT(...) printf("%s\n", #__VA_ARGS__)

int main()
{
    PRINT(hello world);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

C预处理器按预期工作:

$ cc vaargs.c -o vaargs && ./vaargs
hello world

$ cc -V
cc: Sun C 5.12 SunOS_i386 2011/11/16
Run Code Online (Sandbox Code Playgroud)

但是C++预处理器删除了"hello"和"world"之间的空格:

$ CC vaargs.c -o vaargs && ./vaargs
helloworld

$ CC -V
CC: Sun C++ 5.12 SunOS_i386 2011/11/16
Run Code Online (Sandbox Code Playgroud)

c++ solaris c-preprocessor variadic-macros solaris-studio

11
推荐指数
1
解决办法
561
查看次数

使用__VA_ARGS__定义字符串宏时出错

我一直在尝试在C中实现一个函数宏,它将"DEBUG:"添加到参数中,并将其参数传递给printf:

#define DBG(format, ...) printf("DEBUG: " #format "\n", __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

这给了我gcc中的这个错误:

src/include/debug.h:4:70: error: expected expression before ‘)’ token
#define DBG(format, ...) printf("DEBUG: " #format "\n", __VA_ARGS__)
                                                                   ^
Run Code Online (Sandbox Code Playgroud)

据说,它应该串行化格式,并将其变量参数传递给printf,但到目前为止,我无法通过此错误.


编辑

在放弃了字符串化参数和double-hashing(##)后,__VA_ARGS__我现在有了这个错误:

src/lib/cmdlineutils.c: In function ‘version’:
src/lib/cmdlineutils.c:56:17: warning: ISO C99 requires rest arguments to be used [enabled by default]
  DBG("version()");
Run Code Online (Sandbox Code Playgroud)

我应该在争论后放置逗号吗?

DBG("version()",);  // ?
Run Code Online (Sandbox Code Playgroud)

作为参考,DBG()现在看起来像这样:

#define DBG(format, ...) printf("DEBUG: " format "\n", ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

c macros stringification c-preprocessor variadic-macros

10
推荐指数
1
解决办法
8403
查看次数

##__VA_ARGS__ 是什么意思?

我想知道##这个宏定义有什么作用:

#define debug(M, ...) fprintf(stderr,M "\n",##__VA_ARGS __)
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索了一个答案,我想出了以下内容。

##如果没有给宏提供变量参数,将删除逗号。所以,如果宏是这样调用的

debug("message");
Run Code Online (Sandbox Code Playgroud)

没有引号,它被扩展为

fprintf(stderr,"message");
Run Code Online (Sandbox Code Playgroud)

不是

fprintf(stderr,"message",);
Run Code Online (Sandbox Code Playgroud)

为什么要去掉逗号?

c++ macros preprocessor variadic-macros

10
推荐指数
1
解决办法
9324
查看次数

这是检查可变参数宏参数列表是否为空的有效方法吗?

我一直在寻找一种方法来检查可变参数宏参数列表是否为空。我发现所有解决方案似乎都非常复杂,或者使用了非标准扩展。

我想我找到了既紧凑又标准的简单解决方案:

#define is_empty(...) ( sizeof( (char[]){#__VA_ARGS__} ) == 1 )
Run Code Online (Sandbox Code Playgroud)

问:在任何情况下我的解决方案都会失败或调用定义不明确的行为吗?

基于C17 6.10.3.2/2(#运算符):“对应于一个空参数的字符串文字是"",我相信它#__VA_ARGS__总是定义明确的。

宏说明:

  • 这将创建一个复合文字char数组,并使用字符串文字对其进行初始化。
  • 无论将什么传递给宏,所有参数都将转换为一个长字符串文字。
  • 如果宏列表为空,则字符串文字将变为"",它仅包含一个空终止符,因此大小为1。
  • 在所有其他情况下,其大小将大于1。

c c-preprocessor variadic-macros c11

10
推荐指数
1
解决办法
341
查看次数

Variadic宏,零参数和逗号

考虑这个宏:

#define MAKE_TEMPLATE(...) template <typename T, __VA_ARGS__ >
Run Code Online (Sandbox Code Playgroud)

当使用零参数时,它会产生错误代码,因为编译器需要逗号后面的标识符.实际上,VC的预处理器足够聪明,可以删除逗号,但GCC不是.由于宏不能重载,看起来这个特殊情况需要一个单独的宏才能正确,如:

#define MAKE_TEMPLATE_Z() template <typename T>
Run Code Online (Sandbox Code Playgroud)

有没有办法让它工作而不引入第二个宏?

c c++ c-preprocessor variadic-macros

9
推荐指数
1
解决办法
4034
查看次数

Variadic宏,其variadic参数没有参数

调用M其可变参数的参数没有参数的可变参数宏是否合法?

相关标准报价为[cpp.replace]/4:

如果宏定义中的标识符列表不以省略号结尾,则在调用类函数宏时,参数的数量(包括那些不包含预处理标记的参数)应等于宏定义中的参数数量.否则,调用中的参数应该多于宏定义中的参数(不包括...).应该存在一个)终止调用的预处理标记.

对于没有非可变参数的情况,表单中的调用M()应该是合法的,因为调用有一个参数(不包含预处理标记).因此,除了非变量参数之外还有一个参数.

对于具有一个非可变参数的情况,是否应该有一个尾随,,M(1,)以引入一个由variadic参数组成的参数?否则,参数的数量将等于非可变参数的数量.即

#define variadic(x,...) #__VA_ARGS__

variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?
Run Code Online (Sandbox Code Playgroud)

但是,ClangGCC都接受以下测试用例:

#include <iostream>

#define variadic(x,...) #__VA_ARGS__

int main()
{
    std::cout << "'" variadic(1) "'" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

并作为输出产生:

''
Run Code Online (Sandbox Code Playgroud)

这是非标准行为吗?

c++ language-lawyer c-preprocessor variadic-macros c++11

8
推荐指数
1
解决办法
3958
查看次数

变体宏和尾随逗号

我试图在C中进行面向对象,并希望为符号设置一个语法糖宏

object->vtable->method(object, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

send(object, method, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

不幸的是,当一个方法没有参数时,会出现尾随的逗号问题

send(object, method)
Run Code Online (Sandbox Code Playgroud)

object->vtable->method(object, )
Run Code Online (Sandbox Code Playgroud)

是否有任何便携式(无##__VA_ARGS__或Visual Studio)方式?

我想出了一个,但我需要交换对象和方法

#define FIRST_ARG_(N, ...) N
#define FIRST_ARG(args) FIRST_ARG_(args)
#define send(msg, ...) \
 FIRST_ARG(__VA_ARGS__)->vtable->msg(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

许可证

send(method, object)
send(method, object, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

编辑

在下面两个很好的答案的帮助下,我将使用这些宏来完成.它最多可以处理16个参数,但可以轻松扩展

#define SEND_NO_ARG(obj, msg) obj->vtable->msg(obj)
#define SEND_ARG(obj, msg, ...) obj->vtable->msg(obj, __VA_ARGS__)

#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
    arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, \
    arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_CHOOSER(...) \
    GET_18TH_ARG(__VA_ARGS__, …
Run Code Online (Sandbox Code Playgroud)

c c-preprocessor variadic-macros

8
推荐指数
1
解决办法
2559
查看次数