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

C 参数化宏

C 参数化宏,c,macros,c-preprocessor,C,Macros,C Preprocessor,我想不出使用它有什么好处 #define CRANDOM() (random() / 2.33); 而不是 float CRANDOM() { return random() / 2.33; } 它确保对CRANDOM的调用是内联的,即使编译器不支持内联。通过使用#define macro可以强制插入宏体 当使用一个函数时,会有一个函数调用(因此会跳转到函数的地址(除其他外)),这会在一定程度上降低性能 前者通常会更快,即使每次使用#定义的宏时可执行文件的大小都会增加 1

我想不出使用它有什么好处

#define CRANDOM() (random() / 2.33);
而不是

 float CRANDOM() {
    return random() / 2.33;
}

它确保对
CRANDOM
的调用是内联的,即使编译器不支持内联。

通过使用
#define macro
可以强制插入宏体

当使用一个函数时,会有一个函数调用(因此会跳转到函数的地址(除其他外)),这会在一定程度上降低性能

前者通常会更快,即使每次使用#定义的宏时可执行文件的大小都会增加




1编译器可能足够聪明,可以优化函数调用,并内联函数-有效地使其与使用宏相同。但是为了简单起见,我们将在本文中忽略这一点。

调用函数需要一点开销——在本例中,将返回地址推到机器堆栈上并进行分支。通过使用宏,可以避免这种开销。很久以前,这很重要;现在,不管怎样,许多编译器都会插入像这样的内联函数体。一般来说,试图愚弄编译器使其更快地发出代码是愚蠢的游戏;您通常会创建较慢的内容。

首先,
#define
是不正确的,因为结尾处有分号,编译器会在以下方面出错:

float f = CRANDOM() * 2;
其次,我个人试图避免在跨平台代码中分离与平台无关的部分之外使用预处理器,当然,代码只保留用于调试或非调试构建


nightcracker正确地指出它将始终是“有效”内联的,但是如果您可以将函数重新编写为
内联的
,我认为使用预处理器版本没有任何好处,除非所讨论的C编译器没有内联。

前者是旧式的。前者的唯一优点是,如果您有一个遵循旧C90标准的编译器,宏将作为内联。在现代C编译器上,您应该始终编写:

inline float CRANDOM() {
    return random() / 2.33f;
}
其中内联关键字是可选的



(请注意,浮点文字的末尾必须有一个f,否则将强制对double执行计算,然后将其隐式四舍五入为浮点。)

宏将为您提供一个
double
。如果你有一个非常糟糕的编译器,它会少用一个函数调用…@OliCharlesworth;宏是不好的实践的另一个原因;因为C程序员倾向于在他们写的每一行末尾写一个分号;现在的编译器在优化方面已经超过了大多数汇编程序员,但这可能仍然是正确的答案。大多数FPU都是以双精度进行浮点计算的,除非FPU显式设置为单精度模式。@nightcracker如果有FPU可用,也就是说。OP没有提到任何特定的平台。@Lundin另一个注意事项是,编译器可以忽略关键字
inline
,这只是告诉它“我希望你内联这个”,但它可以有效地做它想做的任何事情。你可能想要
静态内联
-否则,您需要在不同的翻译单元中提供具有外部链接的第二个定义(C99与GNU内联语义-参见示例)