算术表达式背景下的宏观扩展
Macro expansion in context of arithmetic expression?
我在网站上看到了下面的代码。我无法理解结果是如何11
的,而不是25
或13
。
为什么我会想25
因为SQ(5) 5*5
或13
因为
SQ(2) = 4;
SQ(3) = 9;
可能是最终结果将13 (9 + 4)
但惊讶地看到结果是11
.结果如何11
?
using namespace std;
#define SQ(a) (a*a)
int main()
{
int ans = SQ(2 + 3);
cout << ans << endl;
system("pause");
}
预处理器对源代码执行简单的文本替换。它对底层语言或其规则一无所知。
在您的示例中,SQ(2 + 3)
扩展到 (2 + 3*2 + 3)
,其计算结果为 11
。
定义SQ
的更可靠方法是:
#define SQ(a) ((a)*(a))
现在,SQ(2 + 3)
将扩展到((2 + 3)*(2 + 3))
,给25
。
尽管这个定义是一个改进,但它仍然不是防弹的。如果SQ()
应用于有副作用的表达式,这可能会产生不良后果。例如:
- 如果
f()
是一个将某些内容打印到控制台并返回int
的函数,SQ(f())
将导致输出被打印两次。 - 如果
i
是int
变量,则SQ(i++)
会导致未定义的行为。
有关宏困难的更多示例,请参阅宏陷阱。
由于这些原因,通常最好使用函数而不是宏。
#define
扩展在编译器看到源代码之前启动。这就是为什么它们被称为预处理器指令,这里的处理器是将 C 转换为机器可读代码的编译器。
因此,这就是宏预处理器传递给编译器的内容:
SQ(2 + 3)
扩展为(2 + 3*2 + 3)
所以,这真的是2 + 6 + 3
= 11
.
怎么能让它做你期望的?
- 强制执行评估顺序。在宏定义或宏调用中使用 ()。或
- 编写一个简单的函数来完成这项工作
预处理器在编译器解释表达式和 C 语法之前执行文本替换。因此,在此代码上运行 C 预处理器将转换:
SQ(2 + 3)
到:
2 + 3*2 + 3
简化为:
2 + 6 + 3
这是 11。
#define preprocesor
语法: # 定义标识符替换
- 当预处理器遇到此指令时,它会通过替换代码其余部分中出现的任何标识符。
- 这种替换可以是表达式、语句、块或简单的任何东西。
- 预处理器不理解 C,它只是通过替换替换任何出现的标识符。
# define 也可以使用参数来定义函数宏:
# define SQ(a) (a*a)
将在编译时将出现的任何 SQ(a) 替换为 a*a。因此
SQ(2+3) 将被 2+3*2+3 取代计算在更换完成后执行。因此回答 2+3*2+3=11
对于您的实现,该值将扩展到 2+3 * 2+3
这将导致 2+6+3=11。
您应该将其定义为:
#define SQ(x) ({typeof(x) y=x; y*y;})
在gcc
上测试,用于输入,例如
- 常数
- 变量 常量
- +常量
- 常量+变量
- 变量++/++变量
- 函数调用,包含 printf。
注意:typeof
是 GNU 对标准 C 的补充,在某些编译器中可能不可用。
它只是编译前的替换
所以你应该试试这个:
#define SQ(a) ((a)*(a))
在你的情况下,SQ(2 + 3)
等价于11
(2+3*2+3)
。
但是把它改成我上面写的,它会像,((2+3)*(2+3))
哪个5*5 = 25
这就是你想要的答案。
- 是否可以通过C++扩展强制多个python进程共享同一内存
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 扩展光电二极管探测器以支持多个传感器
- C++中的VLA,扩展名为std=C++11
- OpenGL 和 GLM 矩阵无法正确扩展,总是按比例缩小
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- C++返回 Numpy 数组的 Python 扩展模块
- 扩展可变参数模板中的变量名称
- 扩展C++生成的代码的模板参数类型名称
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- VSCode IntelliSense无法识别SDL框架的SDL_image扩展库
- 将元组类型扩展为可变参数模板?
- 如何按文件扩展名引用文件夹中的文件
- HDF5Cpp 扩展复合数据集超板问题
- MSVC中的宏观扩展问题
- 嵌套参数包扩展失败
- C4204:使用的非标准扩展:非常量聚合初始值设定项
- 算术表达式背景下的宏观扩展
- GCC与Visual Studio宏观扩展