【问题标题】:Confused about C macro expansion and integer arithmetic [duplicate]对C宏扩展和整数运算感到困惑[重复]
【发布时间】:2010-10-31 07:21:08
【问题描述】:

可能重复:
A riddle (in C)

我有几个关于以下 sn-p 的问题:

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

【问题讨论】:

    标签: c macros c-preprocessor


    【解决方案1】:

    看看这一行:

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

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

    -1 <= (TOTAL_ELEMENTS-2)
    

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

    对循环进行简单的更改即可解决问题:

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

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

    【讨论】:

    • @Miroslav:我用什么后缀来定义宏中的无符号常量。
    • fyi,循环和数组的 C 习惯用法是这样的: int i; for (int i=0; i
    【解决方案2】:

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

    查看更多here

    【讨论】:

    • @Skurmedel:没关系。但是如果我将一个宏定义为#define bb (-64*(sizeof(int)/sizeof(int))) 然后使用 bb,它的行为就像有符号的 int,我认为它应该像 unsigned int 一样,因为在bb 的宏定义是有符号整数与无符号整数的乘法,因此结果应该是无符号整数(C 提升规则)。我是不正确还是遗漏了什么?
    • 根据C99标准(6.3.1.8):否则,如果带符号整数类型的操作数的类型可以表示无符号整数类型的操作数类型的所有值,则无符号整数类型的操作数转换为有符号整数类型的操作数的类型。我猜你的 sizeof 正在返回 unsigned long,其值可以用有符号的 int 表示,因此结果类型是有符号的。
    • 上面部分解释了如果无符号类型的秩等于或大于有符号类型,则有符号类型将转换为无符号类型。也就是说,如果 sizeof 将返回 unsigned int。但是,您的编译器可能有 sizeof 返回 unsigned longs。
    【解决方案3】:

    关于您的问题

    #define AA (-64)
    

    Macro definition and expansionC preprocessor

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

    #define PI 3.14159

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

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

    【讨论】:

      【解决方案4】:

      只回答一个子问题:

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

      #define UNSIGNED_FORTYTWO 42u
      

      这将在您键入 UNSIGNED_FORTYTWO 的任何位置插入一个 unsigned int 文字。

      同样,您经常看到(例如在 中)用于设置确切的浮点类型就足够了:

      #define FLOAT_PI 3.14f
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        相关资源
        最近更新 更多