繁体   English   中英

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

[英]Why do we cast constant literals

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

例如:

#define WIDTH 128

在8位平台上它会等于-128吗?

如果我改变它会怎么样:

#define WIDTH 128U

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

像上面这样的常量整数的默认大小是多少? 它的长度/类型取决于平台架构,还是取决于它们所包含的字面值的类型?

抱歉我的英语不好。

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

WIDTH定义为128U将使其成为无符号整数常量文字。 由于该值适合unsigned int (强制为至少16位宽),因此它具有unsigned int类型。 sizeof(WIDTH)计算为sizeof(unsigned int) ,它完全是特定于平台的。

建议不要使用此后缀。 它会产生令人惊讶的副作用:

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

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

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

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

gcc -Wall -Wextra -Werror

要么

clang -Weverything -Werror

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

首先,在8位平台上128 等于-128

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

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

#define WIDTH   256u
#define HEIGHT  192u

unsigned npixels = WIDTH * HEIGHT;

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

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

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

给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

UINT_MAX - unsigned int可以采用的unsigned int - 保证 至少为 65535


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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM