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

可能重复:
一个谜语(在C中)

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

#include #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?

看看这一行:

 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++) 

如果要在宏中定义无符号常量,请使用通常的后缀( u表示unsignedul表示unsigned long ul )。

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

在这里查看更多。

关于你的问题

 #define AA (-64) 

请参阅C preprocessor中的宏定义和扩展 :

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

#define PI 3.14159

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

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

回答你的一个子问题:

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

 #define UNSIGNED_FORTYTWO 42u 

这将在您键入UNSIGNED_FORTYTWO任何位置插入unsigned int literal。

同样,您经常会看到(例如在中)用于设置确切浮点类型的东西:

 #define FLOAT_PI 3.14f 

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