为什么我们施展不变的文字

时间:2015-12-10 09:53:04

标签: c

我想知道为什么在使用#define预处理器时我们会演变常量?

例如:

#define WIDTH 128

它是否等于8位平台中的-128

如果我这样更改怎么办?

#define WIDTH 128U

在8位平台上它会等同于什么?

上面的常量整数的默认 sizeof 是什么?它的长度/类型取决于平台架构,还是取决于它们所包含的字面值的类型?

抱歉我的英语不好。

3 个答案:

答案 0 :(得分:4)

WIDTH定义为128不会产生任何问题,int在所有符合要求的平台上至少为16位宽。

WIDTH定义为128U会使其成为无符号整数常量文字。由于该值适合unsigned int(强制要求至少16位宽),因此它具有类型unsigned intsizeof(WIDTH)评估为sizeof(unsigned int),这完全取决于平台。

使用此后缀不推荐。它会产生令人惊讶的副作用:

 if (WIDTH > -1) {
    printf("This will never print\n");
 }

由于WIDTH扩展为128U unsigned常量,因此比较将作为无符号比较执行,-1将转换为unsigned并变为{ {1}},一个远大于UINT_MAX的值。不要这样做。

如果您随后将128存储到WIDTH变量中,则可能会出现问题。无论您将其定义为char还是128,实际上都没有区别,如果128U类型为8位且已签名,您仍会有溢出,从而导致未定义的行为。在大多数平台上,存储的值确实是char,但你甚至不能依赖它。

更重要的是,您应该通过启用所有编译器警告并使其出错来使用编译器可以提供的所有帮助:

-128

gcc -Wall -Wextra -Werror

这些警告很少令人讨厌,其中大部分非常有用,并指出了愚蠢的错误,错别字和疏忽。

答案 1 :(得分:2)

首先,{8}平台上的128 等于-128

其次,这与预处理器无关。预处理器的作用是将WIDTH替换为它定义的任何内容。这就是您在源代码中撰写128128u的原因。

后缀u不是类型转换,而是指示文字的类型。在此示例中,128是一个文字,其值为128 int,而128u是一个文字,其值为unsigned int类型128。这里不是问题,但是如果你开始使用它们并且最终大于32767,你可能会遇到问题。例如:

#define WIDTH   256u
#define HEIGHT  192u

unsigned npixels = WIDTH * HEIGHT;

应该注意的是,需要足够使其可移植(可能发生的情况是平台仅使用16位int并且使用int,乘法会溢出,这意味着未定义的行为)。

另请注意,在较新的C标准(但不是古老的标准)中,如果可能的话,将扩展文字以尽可能大。例如,文字32768表示带有值32768的带符号整数类型,如果int不足以容纳该有符号数,则会使用更大的类型。

sizeof这些整数与sizeof(int)相同,因为文字的类型为intunsigned intsizeof(int)的实际值可以是任何正整数。

答案 2 :(得分:1)

给C99章节,因为我手头没有C11文件。

ISO / IEC 9899:1999,6.4.4.1整数常量

  

整数常量的类型是相应列表中可以表示其值的第一个。

对于没有后缀的十进制常量:

  • int
  • long int
  • long long int

对于带uU后缀的小数常量:

  • unsigned int
  • unsigned long int
  • unsigned long long int

ISO / IEC 9899:1999,5.2.4.2.1整数类型的大小

整数类型的宽度是实现定义的,二进制表示也是如此。

INT_MAX - int可以承担的最大值 - 保证 至少 +32767。< / p>

UINT_MAX - unsigned int可以承担的最大值 - 保证 至少 65535。< / p>

ISO / IEC 9899:1999,6.3.1.8通常的算术转换

如果您将intunsigned int进行比较int将隐式转换为unsigned int进行比较。类似于short / long / long long类型。正如@chqrlie指出的那样,这可能是一个问题;如果发生这种情况,你的编译器应该给你一个警告( 总是在启用-Wall -Wextra / /W3的情况下进行编译,不是吗?)。

<强>摘要

即使在8位计算机上,您的常量也会适合int / unsigned int。假设它们不会,编译器会为它们使用下一个最大类型(而不是转换值)。

至于为什么我们这样做......

例如,如果您打算使用WIDTHsizeof()的结果或strlen()的返回代码或unsigned的任何其他内容进行比较从本质上讲,您希望WIDTH具有相同的值域,即能够保存所有可能的值。

这就是为什么你希望WIDTH也是unsigned