无符号字符是否总是提升为 int?

9
假设以下情况:
unsigned char foo = 3;
unsigned char bar = 5;

unsigned int shmoo = foo + bar;

在表达式foo + bar的求值过程中,foobar的值是否保证会提升为int类型的值,还是实现可以将它们提升为unsigned int

根据第6.2.5节第8段:

对于两种有相同符号且不同整数转换等级(见6.3.1.1)的整数类型,具有较小整数转换等级的类型值范围是另一种类型值范围的子集。

根据第6.2.5节第9段:

如果一个int类型可以表示原始类型的所有值,则将该值转换为int;否则,将其转换为unsigned int

较小整数转换等级的整数类型具有值范围是另一种类型值范围的子集的保证似乎取决于整数类型的符号

  • signed char对应于signed int
  • unsigned char对应于unsigned int

这是否意味着unsigned char的值仅保证在unsigned int的子集中,而不一定是int的子集?如果是这样,这是否意味着实现可能理论上有一个unsigned char值不在int的子集中?


深入C语言:整数提升 - Grijesh Chauhan
除非你找到一个 int 是 8 位的系统,否则它应该按照第6.2.5节第9段所指出的方式工作。 - hetepeperfan
@GrijeshChauhan 我认为该网站假定整数类型的最小幅度。我相信实现只需要支持这些最小幅度,但允许定义范围幅度更大(第5.2.4.2.1节:“它们的实现定义值的幅度(绝对值)应等于或大于所示值,并具有相同的符号。”)。 - Vilhelm Gray
@VilhelmGray,我只是问一下,因为你似乎在发布相关的问题。好吧,@Ouah正在帮助你,祝你好运! - Grijesh Chauhan
2
在标准的C编译器中,int 至少要有16位,但是没有什么可以阻止 unsigned charint 一样宽(例如都是24位),这种情况下 unsigned char 将会提升为 unsigned int - Pascal Cuoq
显示剩余2条评论
2个回答

8
实现可以将其提升为unsigned int吗?
如果不是所有的unsigned char值都可以在int中表示(由C99中的6.2.5p9规定),则实现将会提升为unsigned int。请参见下面的实现示例。
那么,这是否意味着实现理论上可能有一个unsigned char值不在int的子范围内?
是的,例如:具有CHAR_BIT 16或32的DSP CPU。
例如,TMS320C55x的TI C编译器:CHAR_BIT为16,UCHAR_MAX为65535,UINT_MAX为65535,但INT_MAX为32767。

http://focus.ti.com/lit/ug/spru281f/spru281f.pdf


我相信这种可能性是char可以被标记为有符号的原因(因为char的所有值都必须适合于int)。相反,C字符集中所有成员的要求迫使一些编译器将char标记为无符号的(例如,在EBCDIC中,我认为数字0-9是0xF0-0xF9)。 - supercat
如果我有这样的东西 int x = 1234char *y = &x1234 的二进制表示是 00000000 00000000 00000100 11010010。我的机器是小端,所以它将其反转并存储在内存中 11010010 00000100 00000000 00000000,LSB 先出现。现在主要部分。如果我使用 printf("%d", *p)printf 将只读取第一个字节 11010010,输出为 -46,但 11010010210,那么为什么会打印 -46。我真的很困惑,我猜可能是某种字符到整数的提升正在做一些事情,但我不知道。 - Suraj Jain
@SurajJain 我想你的意思是 printf("%d" , *y)d 格式说明符写入有符号值,而 11010010 在二进制补码表示中是 -46。使用 printf("%d" , (unsigned char) *y) 来写入无符号值。如果您有更多问题,我建议您打开一个 stackoverflow 问题。 - ouah
先生,我打开了一个问题,当我找到答案后,我写下了它,我想检查它已经好几个月了,你能帮我检查一下吗?我只是想确认我所写的是正确的,不会误导任何人。http://stackoverflow.com/questions/34826036/confused-about-pointer-dereferencing - Suraj Jain
@SurajJain "%d" 期望匹配一个 int 参数。char 作为 int 或极少数情况下的 unsigned 传递给 ... 函数。当作为 unsigned 传递且仍在 [0...INT_MAX] 范围内时,一切都很好。否则会出现未定义行为。 - chux - Reinstate Monica
显示剩余2条评论

0

我昨天遇到了这个问题 - 希望我的答案与主题相关。

uint8_t x =  10;
uint8_t y = 250;

if (x - y > 0) {
    // never happens
}

if (x - y < 0U) {
    // always happens
}

在我看来,似乎值x和y被意外提升了,但实际上是它们的结果被提升了。

我不明白你在说什么。x和y都应该被提升为int,所以你应该得到-240,然后将其提升为无符号数进行比较(4294967056 < 0U),这是不可能发生的。 - newguy

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