[英]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
扩展为128U
( unsigned
常量),因此比较作为无符号比较执行, -1
转换为unsigned
并变为UINT_MAX
,这个值远大于128
。 不要这样做。
如果随后将WIDTH
存储到char
变量中,则可能存在问题。 无论您将其定义为128
还是128U
,实际上都没有区别,如果char
类型为8位且签名,您仍会有溢出,从而导致未定义的行为。 在大多数平台上,存储的值确实是-128
但你甚至不能依赖它。
更重要的是,您应该通过启用所有编译器警告并使其出错来使用编译器可以提供的所有帮助:
gcc -Wall -Wextra -Werror
要么
clang -Weverything -Werror
这些警告很少令人讨厌,其中大部分非常有用,并指出了愚蠢的错误,错别字和疏忽。
首先,在8位平台上128
不等于-128
。
其次,这与预处理器无关。 预处理器的作用是将WIDTH
替换为它定义的任何内容。 这就是为什么你在源代码中写128
或128u
的原因。
后缀u
不是类型转换,它将指示文字的类型。 在此示例中, 128
是一个文字,其值为128,类型为int
而128u
是一个文字,其值为128,类型为unsigned int
。 这里不是问题,但如果你开始使用它们并最终大于32767
你可能会遇到问题。 例如:
#define WIDTH 256u
#define HEIGHT 192u
unsigned npixels = WIDTH * HEIGHT;
应该注意的是,需要足够使其可移植(可能发生的情况是平台仅使用16位int
并且使用int,乘法将溢出,这意味着未定义的行为)。
另请注意,在较新的C标准(但不是古老的标准)中,如果可能的话,将扩展文字以尽可能大。 例如,文字32768
表示带有值32768
有符号整数类型,如果int
不足以容纳该有符号数,则将使用更大的类型。
这些整数的sizeof
与sizeof(int)
相同,因为文字的类型是int
和unsigned int
。 sizeof(int)
的实际值可以是任何正整数。
给C99章节因为我手头没有C11文件。
ISO / IEC 9899:1999,6.4.4.1整数常数
整数常量的类型是相应列表中可以表示其值的第一个。
对于没有后缀的十进制常量:
int
long int
long long int
对于带有u
或U
后缀的十进制常量:
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通常的算术转换
如果将 int
与unsigned int
进行比较 ,则int
将被隐式转换为unsigned int
以进行比较。 类似于short
/ long
/ long long
类型。 正如@chqrlie指出的那样,这可能是一个问题; 你的编译器应该给你一个警告,如果发生这种情况( 你总是编译-Wall -Wextra
/ /W3
启用,不是吗?)。
摘要
即使在8位机器上,你的常量也适合int
/ unsigned int
。 假设它们不会,编译器将使用它们的下一个最大类型(而不是转换值)。
至于为什么我们这样做......
例如,如果您打算使用WIDTH
与sizeof()
的结果或strlen()
的返回代码或其他任何本质上unsigned
的内容进行比较,您可能希望WIDTH
具有相同的值域,即能够掌握所有可能的价值观。
这就是为什么你希望WIDTH
也是unsigned
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.