C++宏:优先级差异的顺序
C++ macros: order of precedence difference?
我有一个简单的代码,可以在法伦海特度和摄氏度之间进行转换。我定义了一些宏来做到这一点,但是当我使用它时,我得到了一些奇怪的结果。当absoluteTemp
= 373.15(水的沸点以开尔文为单位)时,我使用这种方法。
#define kelvinToCelc(k) k - 273.15
#define celcToFahren(c) (9.0 / 5.0) * c + 32
double x = kelvinToCelc(absoluteTemp); // 100
double y = celcToFahren(x); // 212
double z = celcToFahren(kelvinToCelc(absoluteTemp)); // 430.52???
return celcToFaren(kelvinToCelc(absoluteTemp));
在 中扩展宏之后
double z = celcToFahren(kelvinToCelc(absoluteTemp));
它变成了
double z = (9.0 / 5.0) * absoluteTemp - 273.15 + 32
您需要在宏中添加括号
#define kelvinToCelc(k) (k - 273.15)
#define celcToFahren(c) ((9.0 / 5.0) * c + 32)
旧规则是: 在所有内容的宏中使用更多的括号:
#define kelvinToCelc(k) ((k) - 273.15)
#define celcToFahren(c) ((9.0 / 5.0) * (c) + 32)
注意整个宏和所有宏参数周围的括号
新规则是:使用内联函数 他们有类型检查,只计算一次参数,因为他们不需要那么多括号 *
注意:* 某些例外情况可能适用,这不是其中之一
这就是内联函数的样子
inline double kelvinToCelc(double k)
{
return k - 273.15;
}
inline double kelvinToCelc(double c)
{
return (9.0 / 5.0) * c + 32;
}
请注意,您必须将inline
和返回类型放在名称之前,向所有参数添加类型,并在末尾添加;
请注意如何使用换行符使其更易于阅读,以及如何在调试器中单步执行换行
宏
很简单 - 只是一个文本替换
即
double z = celcToFahren(kelvinToCelc(absoluteTemp));
成为
double z = (9.0 / 5.0) * kelvinToCelc(absoluteTemp) + 32
然后变成
double z = (9.0 / 5.0) * absoluteTemp - 273.15 + 32
现在只需做数学运算
即
double z = (9.0 / 5.0) * 373.15 - 273.15 + 32;
如果您要使用宏,请使用括号使您的生活更轻松
#define kelvinToCelc(k) (k) - 273.15
#define celcToFahren(c) (9.0 / 5.0) * (c) + 32
这有助于防止您看到的意外结果。 原因已经在其他帖子中指出
我应该添加到其他答案中的一件事,尝试只运行预处理器并查看输出,即: g++ -E -P main.cpp<</p>
答案 431.52 是正确的。它像这样扩展
(9.0/5.0) * 373.15 - 272.15 + 32
在数学中,[* 和/] 优先于 [+ 和 -]。所以等式扩展为像
((9.0/5.0) * 373.15) - 272.15 + 32
(671.67) - 272.15 + 32
399.52 + 32
431.52
[* 和/] 具有相同的优先级,因此顺序无关紧要,同样 [+ 和 -] 具有相同的优先级,因此它们的执行顺序无关紧要。
对于宏,它只依赖于文本替换。所以它相当于:
double z = (9.0 / 5.0) * absoluteTemp - 273.15 + 32;
这就是为什么你得到错误的结果。
编辑:
尝试使用(内联)函数,即使您可以通过添加更多括号来使其工作:(见#2)
#define celcToFahren(c) ((9.0 / 5.0) * (c) + 32)
宏也容易出错,因为它们依赖于文本替换并且不执行类型检查。查看此处了解更多信息。
相关文章:
- CMake-按正确顺序将项目与C运行时对象文件链接
- 函数调用中参数的顺序重要吗
- 为什么不;名字在地图上是按顺序排列的吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 数到第n个楼梯的路(顺序无关紧要)
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 如何使C++编译器遵循与C#在该赋值语句中相同的优先级、关联性和求值顺序
- C++优先级队列不遵循 FIFO 顺序
- C++ 中的优先级队列在 pop() 之后顺序不正确
- C++宏:优先级差异的顺序
- STL 优先级队列按递增顺序排列
- 在同一优先级队列中创建递增和递减顺序选项
- 对的优先级队列以相反的顺序排列
- 运算符优先级顺序和计算混淆
- 内置类型的Do对象具有特殊的静态初始化顺序优先级
- 反转优先级队列中元素的顺序
- C语言中等优先级操作数的计算顺序
- 优先级队列的反向顺序
- 运算符优先级和计算顺序
- 从相同的结构体以相反的顺序创建两个优先级队列