简体   繁体   English

算术表达式上下文中的宏扩展?

[英]Macro expansion in context of arithmetic expression?

I saw this below code in an website. 我在网站上看到了以下代码。 I could not able to understsnd how the result is coming as 11 , instead of 25 or 13 . 我无法判断结果如何变为11 ,而不是2513

Why I am thinking 25 because SQ(5) 5*5 为什么我在想25因为SQ(5) 5*5

or 13 because 13因为

SQ(2) = 4;

SQ(3) = 9;

may be final result will be 13 (9 + 4) But surprised to see result as 11 . 可能是最终结果将是13 (9 + 4)但是惊讶地看到结果为11 How the result is coming as 11 ? 结果如何成为11

using namespace std;
#define SQ(a) (a*a)
int main()
{
    int ans = SQ(2 + 3);
    cout << ans << endl;
system("pause");
}

The preprocessor does a simple text substitution on the source code. 预处理器在源代码上执行简单的文本替换。 It knows nothing about the underlying language or its rules. 它对基础语言或其规则一无所知。

In your example, SQ(2 + 3) expands to (2 + 3*2 + 3) , which evaluates to 11 . 在您的示例中, SQ(2 + 3)扩展为(2 + 3*2 + 3) ,其值为11

A more robust way to define SQ is: 定义SQ更健壮的方法是:

#define SQ(a) ((a)*(a))

Now, SQ(2 + 3) would expand to ((2 + 3)*(2 + 3)) , giving 25 . 现在, SQ(2 + 3)将扩展为((2 + 3)*(2 + 3)) ,得到25

Even though this definition is an improvement, it is still not bullet-proof. 虽然这个定义是一种改进,但它仍然不是防弹的。 If SQ() were applied to an expression with side effects , this could have undesired consequences. 如果将SQ()应用于具有副作用的表达式,则可能会产生不良后果。 For example: 例如:

  • If f() is a function that prints something to the console and returns an int , SQ(f()) would result in the output being printed twice. 如果f()是一个向控制台输出内容并返回int的函数,则SQ(f())将导致输出被打印两次。
  • If i is an int variable, SQ(i++) results in undefined behaviour . 如果iint变量,则SQ(i++)导致未定义的行为

For further examples of difficulties with macros, see Macro Pitfalls . 有关宏的困难的更多示例,请参阅宏陷阱

For these reasons it is generally preferable to use functions rather than macros. 由于这些原因,通常优选使用函数而不是宏。

#define expansions kick in before the compiler sees the source code. #define扩展在编译器看到源代码之前启动。 That is why they are called pre-processor directives , the processor here is the compiler that translates C to machine readable code. 这就是为什么它们被称为预处理器指令 ,这里的处理器是将C转换为机器可读代码的编译器。

So, this is what the macro pre-processor is passing on to the compiler: 所以,这就是宏预处理器传递给编译器的原因:

SQ(2 + 3) is expanded as (2 + 3*2 + 3) SQ(2 + 3)扩展为(2 + 3*2 + 3)

So, this is really 2 + 6 + 3 = 11 . 所以,这真的是2 + 6 + 3 = 11

How can you make it do what you expect? 你怎么能让它做你期望的?

  1. Enforce the order of evaluation. 强制执行评估顺序。 Use (), either in the macro definition or in the macro call. 在宏定义或宏调用中使用()。 OR 要么
  2. Write a simple function that does the job 写一个简单的功能来完成这项工作

The C preprocessor does textual substitution before the compiler interprets expressions and C syntax in general. C预处理器在编译器解释表达式和C语法之前进行文本替换。 Consequently, running the C preprocessor on this code converts: 因此,在此代码上运行C预处理器会转换:

SQ(2 + 3)

into: 成:

2 + 3*2 + 3

which simplifies to: 这简化为:

2 + 6 + 3

which is 11. 这是11。

It's just a replacement before compilation 它只是在编译之前的替代品

so you should try this out : 所以你应该试试这个:

#define SQ(a) ((a)*(a))

In your case , SQ(2 + 3) is equivalent to (2+3*2+3) which is 11 . 在您的情况下, SQ(2 + 3)相当于(2+3*2+3) ,即11

But correcting it to as I wrote above, it will be like, ((2+3)*(2+3)) which is 5*5 = 25 that's the answer you want. 但正如我在上面所写的那样纠正它,它会像((2+3)*(2+3)) ,即5*5 = 25 ,这就是你想要的答案。

#define preprocesor #define preprocesor

Syntax : # define identifier replacement 语法: #define identifier replacement

  1. When the preprocessor encounters this directive, it replaces any occurrence of identifier in the rest of the code by replacement. 当预处理器遇到此指令时,它会替换替换代码中其余代码中的任何标识符。
  2. This replacement can be an expression, a statement, a block or simply anything. 这种替换可以是表达,陈述,块或简单的任何东西。
  3. The preprocessor does not understand C, it simply replaces any occurrence of identifier by replacement. 预处理器不理解C,它只是通过替换替换任何出现的标识符。

# define can work also with parameters to define function macros: #define也可以使用参数来定义函数宏:

# define SQ(a) (a*a)

will replace any occurance of SQ(a) with a*a at compile time. 将在编译时用* a替换任何SQ(a)的出现。 Hence, 因此,

SQ(2+3) will be replaces by 2+3*2+3 The computation is performed after the replacement is done. SQ(2 + 3)将被替换为2 + 3 * 2 + 3在更换完成后执行计算。 hence answer 2+3*2+3=11 因此回答2 + 3 * 2 + 3 = 11

For your implementation, the value will expand to 2+3 * 2+3 which will result into 2+6+3=11. 对于您的实现,该值将扩展为2+3 * 2+3 ,这将导致2 + 6 + 3 = 11。

You should define it as: 您应该将其定义为:

#define SQ(x) ({typeof(x) y=x; y*y;})

Tested on gcc , for inputs like 测试gcc ,输入如

  1. constants, 常量,
  2. variable, 变量,
  3. constant+const 不变+常量
  4. const+variable 常量+可变
  5. variable++ / ++variable 变量++ / ++变量
  6. function call, containing printf. 函数调用,包含printf。

Note: typeof is GNU addition to standard C. May not be available in some compilers. 注意: typeof是标准C的GNU添加。可能在某些编译器中不可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM