这两个宏有什么区别吗?
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)))
除了第一个宏周围的括号外,我发现这两个宏之间没有区别。
是可读性问题还是处理运算符优先级的方法?
#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)))