这两个宏有什么区别吗?

Is there any difference between this two macros?

除了第一个宏周围的括号外,我发现这两个宏之间没有区别。

是可读性问题还是处理运算符优先级的方法?

#define TAM_ARRAY(a) (sizeof(a)/sizeof(*a))
#define TAM_ARRAY2(a) sizeof(a)/sizeof(*a)

宏的工作方式是代码在编译时是"swapped out"。 所以像

#define ADD(i, j) i + j
int k = ADD(1, 2) * 3 

将被视为:int k = 1 + (2 * 3)

然而,

#define ADD(i, j) (i + j)
int k = ADD(1, 2) * 3

将被视为:int k = (1 + 2) * 3

因此,由于运算符优先级的原因,可能有两个宏。

是的,有区别。需要括号以便将宏的结果计算为单个表达式,而不是与使用宏的周围上下文混合。

这个程序的输出:

#include <stdio.h>

#define TAM_ARRAY(a) (sizeof(a)/sizeof(*a))
#define TAM_ARRAY2(a) sizeof(a)/sizeof(*a)

int main(void)
{
    int x[4];
    printf("%zu\n", 13 % TAM_ARRAY (x));
    printf("%zu\n", 13 % TAM_ARRAY2(x));
}

是,在 C 实现中,int 是四个字节:

1
3

因为:

  • 13 % TAM_ARRAY (x) 替换为 13 % (sizeof(x)/sizeof(*x)),分组为 13 % (sizeof(x) / sizeof(*x)),计算结果为 13 % (16 / 4),然后是 13 % 4,然后是 1 .
  • 13 % TAM_ARRAY2(x) 替换为 13 % sizeof(x)/sizeof(*x),分组为 (13 % sizeof(x)) / sizeof(*x),计算结果为 (13 % 16) / 4,然后是 13 / 4,然后是 3 .

按照这些思路,TAM_ARRAY 最好在 a 的第二个实例周围加上括号:

#define TAM_ARRAY(a) (sizeof(a)/sizeof(*(a)))

宏在代码翻译的早期阶段被文本替换。除非特别预期会产生副作用,否则在宏展开式和宏展开式本身(如果它是表达式)中完全括起宏参数非常重要。

在发布的案例中,您不太可能遇到问题,因为很少有运算符具有更高的优先级,并且它们可能不会在宏扩展周围使用,但这是一个病态的示例:

  • TAM_ARRAY(a)["abcd"] 扩展为 (sizeof(a)/sizeof(*a))["abcd"]
  • TAM_ARRAY2(a)["abcd"] 扩展为 sizeof(a)/sizeof(*a)["abcd"],相当于 sizeof(a) / (sizeof(*a)["abcd"]).

但是请注意,在宏扩展之前放置具有相同优先级的运算符,例如 % 肯定会导致问题,如 Eric Postpischil 的回答中所述。

另请注意,a 也应加括号:

#define TAM_ARRAY(a) (sizeof(a) / sizeof(*(a)))