"#define"和内联行为是否相同?

Kai*_*ije 3 c c++ inline-functions c-preprocessor

我在我的一个标题中有一些简短的定义,如下所示:

#define ROUND_DOWN(a,b)   (a)-(a)%(b)
Run Code Online (Sandbox Code Playgroud)

例如

ROUND_DOWN(178,32) = 160
Run Code Online (Sandbox Code Playgroud)

但是,如果我把它传递给它:

ROUND_DOWN(160*2, 32);
Run Code Online (Sandbox Code Playgroud)

然后它像这样编译?

(160*2)-(160*2)%(32), 
Run Code Online (Sandbox Code Playgroud)

这只是处理160*2两次..

我想知道内联函数是否以相同的方式运行?例如

inline int RoundDown(int a, int b)
{
return (a)-(a)%(b)
}
Run Code Online (Sandbox Code Playgroud)

将160*2作为320存储在"int a"中,然后计算会起作用,还是它的行为与定义相同?

一个更好的例子是:

RoundDown((x+x2)*zoom, tile_width);
Run Code Online (Sandbox Code Playgroud)

Alo*_*ave 8

"#define"和内联行为是否相同?

不,他们不!

宏和内联函数之间存在许多差异.

- 没有评估时间

作为内联函数的参数传递的表达式将被计算一次.

在某些情况下,作为参数传递给宏的表达式可以多次计算.每次在宏中使用参数时,都会评估该参数.

代码示例:

#define max(a,b) (a>b?a:b)

int main()
{

  int a = 0;
  int b = 1;

  int c = max(a++, b++);

  cout << a << endl << b << endl;
  return 0;

}
Run Code Online (Sandbox Code Playgroud)

意图可能是打印1和2,但宏扩展为:

int c = a++ > b++ ? a++ : b++;
Run Code Online (Sandbox Code Playgroud)

b增加两次,程序打印1和3.

- 谁评估他们

内联函数由编译器评估,而预编译器在预编译时评估宏.

- 类型检查

内联函数遵循在正常函数上强制执行的所有类型安全协议.检查参数类型,并正确执行必要的转换.在将内联函数放入符号表之前,编译器执行返回类型检查,函数签名.
它们可以被重载以对正确类型的数据执行正确的操作.

与内联函数相比,宏更容易出错.参数未键入(宏适用于任何算术类型的对象).编译期间未进行错误检查.

代码示例:

#define MAX(a, b) ((a < b) ? b : a)

int main( void)
{
   cout << "Maximum of 10 and 20 is " << MAX("20", "10") << endl;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

可以将字符串传递给执行某种整数运算的宏,并且宏不会抱怨!

- 建议还是命令?

内联只是对编译器的建议.编译器决定是否内联扩展函数.

宏将永远扩展.

- 调试怎么样?

内联函数可以轻松调试,因为您可以在内联函数定义中设置断点并逐步进入调试方法.

宏不能用于调试,因为它们在预编译时扩展.


unw*_*ind 5

首先,您应该假设在编译时计算所有常量表达式,以便在运行程序时乘法永远不会存在.

其次,你根本不能依赖inline任何效果,它只是对编译器的暗示,而不是一个要求.

但即使函数没有内联,表达式也不会被计算两次,因为参数传递要求在函数体运行之前对其进行求值.