Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.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_C Preprocessor - Fatal编程技术网

C 宏与静态内联?

C 宏与静态内联?,c,c-preprocessor,C,C Preprocessor,使用宏而不是静态内联方法有什么显著的好处吗?特别是,如何使用静态内联方法实现varargs在调用链中的进一步传递,这可以通过宏一步完成 #define myprintf(fmt, args...) printf (fmt, args) 这只是一个简单的例子,但我仍然好奇是否有一种等效的方法可以使用静态内联而不使用va_args步骤来实现这一点 编译器内联静态内联方法也是如此吗?它们的尺寸是多少?调用任意子方法怎么样?如果我使用几个宏,所有宏都会编译成一个表达式,因此编译器可能更容易进行优化。编

使用宏而不是静态内联方法有什么显著的好处吗?特别是,如何使用静态内联方法实现varargs在调用链中的进一步传递,这可以通过宏一步完成

#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__)