C 宏与静态内联?
使用宏而不是静态内联方法有什么显著的好处吗?特别是,如何使用静态内联方法实现varargs在调用链中的进一步传递,这可以通过宏一步完成C 宏与静态内联?,c,c-preprocessor,C,C Preprocessor,使用宏而不是静态内联方法有什么显著的好处吗?特别是,如何使用静态内联方法实现varargs在调用链中的进一步传递,这可以通过宏一步完成 #define myprintf(fmt, args...) printf (fmt, args) 这只是一个简单的例子,但我仍然好奇是否有一种等效的方法可以使用静态内联而不使用va_args步骤来实现这一点 编译器内联静态内联方法也是如此吗?它们的尺寸是多少?调用任意子方法怎么样?如果我使用几个宏,所有宏都会编译成一个表达式,因此编译器可能更容易进行优化。编
#define myprintf(fmt, args...) printf (fmt, args)
这只是一个简单的例子,但我仍然好奇是否有一种等效的方法可以使用静态内联而不使用va_args步骤来实现这一点
编译器内联静态内联方法也是如此吗?它们的尺寸是多少?调用任意子方法怎么样?如果我使用几个宏,所有宏都会编译成一个表达式,因此编译器可能更容易进行优化。编译器是否总是足够聪明,可以将多级静态内联调用转换为单个表达式 使用宏而不是静态内联方法有什么显著的好处吗? 宏不进行类型检查,也不计算其参数,这带来了巨大的威力和巨大的危险 因此(引用一个众所周知的例子) 这似乎是一个比
static inline int max(a,b) { return (a>b)?a:b; }
由于它不需要int
参数(即适用于支持
运算符的所有类型),因此
- 它计算
或a
两次(考虑b
)MAX(a++,b++)
- 它有可能出现运算符优先级问题
#define MAX(a,b) ((a)>(b)?(a):(b))
如何使用静态内联方法实现varargs在调用链中的进一步传递,该方法可以通过宏一步完成?
C99支持可变宏,gcc
对该宏定义了(非标准)扩展
实际上有两种格式:
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)
其中,\uu VA\u ARGS\uu
被可变元素替换;这是标准的C99
gcc
还提供:
#define debug(format, args...) fprintf (stderr, format, args)
其中,args
可以表示多个参数
在第一个公式中,仅使用gcc
,您可以处理完全忽略的参数,并使用粘贴宏运算符##
避免多余的逗号,即:
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
实现这一目标是不可能的
[编译器是否总是]内联静态内联方法?
不,编译器可以自由执行它想要的操作。它可以内联它们,或者为每个编译单元生成一组目标代码。但是,至少在理论上,它可以对
#define
'd宏执行相同的操作。编译器不会总是将多个级别的内联宏转换为单个表达式,因为即使单个内联宏实际上也可能不是内联编码的;通常情况下,编译器比程序员更能判断这是否是一个好主意。“编译器是否总是足够聪明…?”这取决于编译器。C99具有可变参数宏。我更正了代码示例中的空格。正如所写,myprintf
不是一个宏函数,在它出现的地方将被(fmt,args…)printf(fmt,args)
所取代。#定义调试(…)fprintf(stderr,u VA_uargs_u)
可以在这里实现同样的效果,没有使用gcc扩展。@PaulGriffiths您的观点是没有参数的..
是非标准的,####!!!!!!!!!!!!!!!!!!!!!!!!!!33?我认为这是对的,我会修正。是的,没错,从C99开始是标准的,但它要求您至少提供一个参数,所以我的示例演示了如何以基于标准的方式获得与相同的效果。@PaulGriffiths确实修正了。
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)