在C ++中,在某些上下文中,括号可能会更改所包含表达式的含义(对于给定的上下文)。例如,decltype(expr)和decltype((expr))经常会出现不同的类型:
int x;
decltype(x) a=x; // type int; a initialized with a copy of x
decltype((x)) b=x;//type int&; b is a reference to x; extra parentheses matter!
但是C呢?
将宏参数括在括号中是C中常见的做法,会产生一些意想不到的副作用吗?
[编辑]更确切地说,如果括号对于分组来说是多余的,那么它们是否会改变程序含义?
我只考虑表达式(不是其他语法元素,如类型,函数参数列表等)。
答案 0 :(得分:1)
我相信答案是“不”。
我不知道在((blah))
中添加额外的一对不必要的括号会改变含义的情况。正如您所说,这对于大多数宏定义至关重要。
但是,在各种情况下,显式分组可能导致与数学规则无关的更改。我不是指(1+2)*3
;那只是数学。我的意思是编译器最终生成一个不同但相当的代码序列,这个代码序列的效率更高,或者更低。
例如,考虑这个功能;
float fourth_power (float n) {
return n*n*n*n;
}
它可以对此功能执行不同的操作:
float fourth_power (float n) {
return (n*n)*(n*n);
}
在纯数学中,结果应该是相同的,但实际上有限大小的浮点值,你可以得到一个不同的数字答案,但这不是我在这里所说的。
我正在谈论的变化是第二种形式运行得更快。如果你知道你只使用较小的数字(浮点数的限制不是问题),那么你可能希望以速度提升的第二种方式编码。
事实上,如果你使用-ffast-math
,GCC会进行这种转换,但通常编译器会安全地使用它。
这是一个可能适用于所有编译器的示例(因为它与数值精度有关),但是有很多例子显然任意分组决策可以将特定编译器放在不同的内部决策路径上,并且可以有趣,以及性能,代码大小等方面的可测量差异
答案 1 :(得分:0)
也许你的意思是这样的:
#define SIMPLE_USELESS_MACRO(X) (X)
int int_ = 2;
long int long_int_ = 2L;
double double_ = 3.14;
double result = long_int_ + SIMPLE_USELESS_MACRO(int_ + double_);
如果我是对的,如果括号在x左右,则转换序列如下:
(假设没有编译器优化)
1)int - >双 2)long int - >双
如果没有括号,转换顺序为:
1)int - >长整数 2)long int - >双
我不确定上述转换的时间,但可能整数 - >浮点转换需要更多时间(假设没有硬件单位对此负责)。
这只是一个建议,如果我错了抱歉。
答案 2 :(得分:0)
这样的事情?
#define ODD( n ) n % 2
int a = 2;
bool n1 = ODD( a + 1 ); // a + 2 % 2
bool n2 = ODD( (a+1) ); // (a + 2) % 2
n1 true (!=0)
n2 false (==0)