gcc: 警告:大整数隐式截断为无符号类型

7
#include<stdio.h>

int main()
{

    unsigned char c;
    c = 300;
    printf("%d",c);
    return 0;
}

输出是否可预测还是未定义的?
2个回答

10

非常抱歉第一次的答复,以下是C++标准中的解释:

输出是否可预测或者说是不确定的?

它是可预测的。在这段代码中要注意两点:首先是将无法存储在unsigned char类型中的值进行赋值:

unsigned char c;
c = 300;
3.9.1 基本类型 (第54页) 声明为unsigned的无符号整数应当遵守算术模2n的规律,其中n是该整数大小所表示的位数。这意味着无符号算术不会溢出,因为无法用结果表示的无符号整数类型会被减少到比结果能够表示的无符号整数类型的最大值还要小1的数字。
c = 300 % (std::numeric_limits<unsigned char>::max() + 1);

其次,在使用printf的格式字符串中传递%d以打印unsigned char变量。
这位ysth解答得很好 ;) 这里没有未定义的行为,因为在可变参数的情况下会发生从unsigned char到int的提升转换!

注意:答案的第二部分是对此答案评论所说内容的改述,但不是我的原始答案。


"numeric_limit" 实际上是 "numeric_limits"。 - shadyabhi
2
如果你愿意的话,可以购买官方文档,或者直接访问http://www.open-std.org/jtc1/sc22/wg21/并免费下载最新的草案:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf。 - Khaled Alshaya
我是这个网站的新手。我只是想知道,你们是如何如此迅速地知道这个问题被问到的呢?为什么你们能够如此快速地收到有关该问题的提醒? - shadyabhi
@Shadyabhi,您可以在StackOverflow主页右侧的“有趣标签”中添加任何您喜欢的“标签”。这些问题将会被突出显示 :) - Khaled Alshaya
但是对于数字300%(UCHAR_MAX+1),结果当然是有定义的,因为它保证可以被一个int表示。我为了完整性而添加了上述内容。 - Alok Singhal
显示剩余2条评论

4

赋值的结果应该是可预测的:

3.9.1

4 声明为unsigned的无符号整数,应当遵守算术模2 n 的规则,其中n是该特定大小的整数的值表示中的位数。17)

17)这意味着无符号算术不会溢出,因为不能由所得的无符号整数类型表示的结果将被模减,模数是可以由所得的无符号整数类型表示的最大值加1。

此外,sizeof(char)定义为1,sizeof(unsigned char)= sizeof(char),因此您应该看到相同的结果,而不管实现方式如何(假设您没有字节大小不同于8的有趣大小)。

然而,警告告诉您结果可能不是您想要的(例如,也许您高估了无符号类型的大小?)。如果这是您想要的,请为什么不写300%(1 << CHAR_BIT)(假设300对您有某种重要性)?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接