【问题标题】:Ununderstandable function-like macro in CC中无法理解的类函数宏
【发布时间】:2014-05-28 11:22:47
【问题描述】:

我有这个 c 宏代码:

#define d(x, y, z) (    \
      x += z,               \
      y += x,               \
      x += y                \

)

我有几个问题:

  1. 这个宏函数有返回值吗? (例如,返回 x、y 或 z) 还是只是将参数变量与自身相加? (这是 没用的,我认为)。
  2. \ 是什么意思?
  3. 为什么原始编码器每次操作后都使用comma-operator?为什么不直接使用; 而不是,

任何帮助将不胜感激

【问题讨论】:

  • 顺便说一句,这段代码很糟糕,如果你想使用它会添加很多错误。
  • 猜猜int a=1,b=2,c=3,d=4;int a=1;int b=d(1,a,3);的结果?
  • “C 中可理解的宏”有点矛盾。
  • 使用逗号运算符和包围() 使整个事情成为一个简单的语句,这意味着宏可以例如放在if 之后(没有{})而不必担心这将导致if 子句损坏。使用{} 也可以,但我隐约记得在某些情况下() 更好。
  • 是的,正如@BryanChen 指出的那样,宏修改它的一个操作数通常不是一个好主意,尤其是修改几个操作数是不明智的。相比之下,可能会导致混淆,使逗号问题看起来像是小游戏。

标签: c function macros


【解决方案1】:

这个宏函数有返回值吗? (例如返回 x、y 或 z)还是只是将参数变量与自身相加? (我认为这是没用的)。

它修改变量的值。 “返回”值是x的最终值。

\是什么意思?

当放在最后一行时,它会否定换行符,以便宏定义可以跨越多行。

为什么原始编码器在每次操作后都使用逗号运算符?为什么不直接使用 ; 而不是 `, ?

宏替换文本。考虑以下代码:

int x=1, y=2, z=3, f;
f = 3 * (d(x,y,z));

如果宏使用逗号,代码变为:

int x=1, y=2, z=3, f;
f = 3 * (x+=z, y+=x, x+=y);  // Evaluates to 3 * (the final value of x)

如果宏使用分号,代码变为:

int x=1, y=2, z=3, f;
f = 3 * (x+=z; y+=x; x+=y);  // Syntax error!!!

【讨论】:

  • 可以通过在宏中添加{}来避免语法错误。所以它变成了({x+=z; y+=x; x+=y})
  • @BryanChen 你忘了最后一个分号({x+=z; y+=x; x+=y;})
  • @BryanChen:你可以在表达式中使用复合语句吗?
  • @undur_gongor 它是GCC extension
  • @Bryan 我尽量坚持可移植的构造/建议,除非问题是关于非标准行为。
【解决方案2】:

1) 宏本身不返回任何内容。它只是一段愚蠢的代码,无论在哪里遇到它都会被预处理器逐字替换。它可以是任何类型的文本。

2) \ 用于让预处理器知道当前宏也在下一行展开。 (多行宏)

3) 我无法对原始编码员的意图做出任何假设。但是,通过在其中使用逗号运算符,整个宏变成了 C 语言表达式。例如运行这样的东西(如果有分号就不会):

int a = 0;

int x = 1;
int y = 2;
int z = 3;

a = d(x, y, z);

printf("a = %d\n", a);
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("z = %d\n", z);

并打印:

a = 10
x = 10
y = 6
z = 3

【讨论】:

  • @BryanChen - 在不咨询律师的情况下,我将其定义为返回可分配值的东西,(,,) 表达式将返回最后一个内部表达式的值——在本例中为值x.
  • 是的,重要的是,当需要分叉时,了解宏本身只返回一个字符串,并将其返回给编译器,然后编译器将其嵌入到源代码中代替宏调用。无论宏在程序级别“返回”什么“值”,都与“硬编码”主程序源代码中的等效源代码序列返回的值完全相同。
【解决方案3】:

首先,#define 是一个预处理器指令,这意味着当源代码/c 代码被编译时,#define 将 LHS 替换为 RHS - 这意味着无论在哪里使用 d(x,y,z) 都将替换为给定方程

例如,下面的 c 代码将打印 - 修改后 a = 9, b=8, c=9

#define d(x,y,z) \
    x+=1,       \
    y+=2,       \
    z+=3       


#include <stdio.h>

 int main()
 {
    unsigned int a,b,c;
    a=5;
    b=6;
    c=7;

    printf("modified a = %d, b=%d, c=%d \n",d(a,b,c));    
}

这里发生的基本上是 d(a,b,c) - 替换为 a+=1,b+=2,c+=3

  1. \ 的含义是预处理器指令在下一行继续。
  2. 至于逗号操作符,我们需要查看源代码以了解它的具体使用位置。正如您在上面的代码中看到的那样,逗号运算符实际上分隔了所有三个变量并且能够正确打印 - 如果我用任何其他运算符替换逗号,我们将得到编译错误。

希望这能回答你的问题:)

问候 哈里

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多