对C宏扩展和整数运算感到困惑

时间:2009-06-04 11:52:51

标签: c macros c-preprocessor

  

可能重复:
  A riddle (in C)

关于以下代码段,我有几个问题:

#include<stdio.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main()
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);

return 0;
}

此处代码的输出不会按预期打印数组元素。但是当我添加一个(int)的类型转换时,ELEMENTS的宏定义为

 #define TOTAL_ELEMENTS (int) (sizeof(array) / sizeof(array[0]))

它按预期显示所有数组元素。

  • 这种类型转换是如何工作的?

基于此,我几乎没有问题:

  • 这是否意味着我有一些宏定义:

    #define AA (-64)

默认情况下,在C中,所有定义为宏的常量都等同于 signed int

如果是,那么

  • 但是,如果我必须强制在宏中定义一些常量,因为unsigned int是否有任何常量后缀而不是我可以使用(我试过UL,UD既不起作用)?

  • 如何在宏定义中定义常量以表现为unsigned int?

4 个答案:

答案 0 :(得分:12)

看看这一行:

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)

在第一次迭代中,您正在检查是否

-1 <= (TOTAL_ELEMENTS-2)

运算符size_of返回无符号值,检查失败(在32位机器上签名为-1 signed = 0xFFFFFFFF)。

循环中的一个简单更改可以解决问题:

for(d=0;d <= (TOTAL_ELEMENTS-1);d++)
printf("%d\n",array[d]);

回答你的其他问题:C宏是按文本扩展的,没有类型的概念。 C编译器将您的循环视为:

for(d=-1;d <= ((sizeof(array) / sizeof(array[0]))-2);d++)

如果要在宏中定义无符号常量,请使用通常的后缀(uunsignedulunsigned long

答案 1 :(得分:7)

sizeof以无符号格式返回字节数。这就是你需要演员的原因。

查看更多here

答案 2 :(得分:3)

关于

的问题
#define AA (-64)

请参阅C preprocessor中的Macro definition and expansion

  

类似对象的宏通常被用作良好编程实践的一部分,为常量创建符号名称,例如。

     

#define PI 3.14159

     

...而不是在整个代码中对这些数字进行硬编码。但是,C和C ++都提供了const指令,它提供了另一种避免整个代码中硬编码常量的方法。

定义为宏的常量没有关联类型。尽可能使用const

答案 3 :(得分:1)

回答您的一个子问题:

要“在宏中定义常量”(这有点草率,你没有定义一个“常量”,只是做一些无符号的文本替换技巧),你应该使用'u'后缀:

#define UNSIGNED_FORTYTWO 42u

这将在您键入unsigned int的任何位置插入UNSIGNED_FORTYTWO字面值。

同样,您经常会看到(在&lt; math.h&gt;中)用于设置精确浮点类型的足迹:

#define FLOAT_PI 3.14f

这会在代码中键入float的任何位置插入FLOAT_PI(即“单精度”)浮点文字。