C语言中的数据类型提升

6
在以下代码中:
#include "stdio.h"
signed char a= 0x80;
unsigned char b= 0x01;


void main (void)
{
    if(b*a>1)
        printf("promoted\n");
    else if (b*a<1)
        printf("why doesnt promotion work?");

    while(1);
}

我原本期望会输出"promoted",但实际上没有。为什么呢?如果我将数据类型更改为有符号和无符号整数,并将a设置为负数,例如0x80000000,将b设置为正数,例如0x01,则会按预期输出"promoted"。

请帮助我理解问题所在!

2个回答

10

你刚刚被 C 语言的混乱类型提升规则所困扰。

在 C 语言中,比 int 更小的整数类型会自动提升为 int 类型。

所以你有:

0x80 * 0x01 = -128 * 1

0x80被扩展为带符号的int类型:

0xffffff80 * 0x00000001 = -128 * 1 = -128

结果是-128,因此小于1


当您使用类型intunsigned int时,两个操作数都会被提升为unsigned int。 因为在无符号整数中 0x80000000 * 0x01 = 0x80000000 大于 1


这里是发生的类型提升的并排比较:

(signed char) * (unsigned char) -> int
(signed int ) * (unsigned int ) -> unsigned int

(signed char)0x80       * (unsigned char)0x01 -> (int)         0xffffff80
(signed int )0x80000000 * (unsigned int )0x01 -> (unsigned int)0x80000000

(int)         0xffffff80 is negative   ->   prints "why doesnt promotion work?"
(unsigned int)0x80000000 is positive   ->   prints "promoted"

这里提供了C语言中类型提升规则的参考。


@Mystical 我不理解你的回答。即使它被扩展为 int 类型并带符号,我认为它并没有被扩展,但假设它被扩展了,为什么它没有被提升为无符号 int,并且乘积变成一个正数呢? - Dom045
+1 - 这个回答比我的好得多/更相关(所以我删除了它) - Alex Z
@Dom045 因为规范是这样规定的。signed charunsigned char 都比 int 低级,因此它们都会被提升为 int。在 signed int vs. unsigned int 的情况下,标准规定它们都将转换为 unsigned int。有关规则可以在此处找到:https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules - Mysticial
@Mystical:好的,我不知道字符会被提升为整数。我的错。但请帮我理解一下。如果“在有符号整数与无符号整数的情况下,标准规定它们都应转换为无符号整数。”那么乘积不应该是无符号的,因此是正数吗?我只是对提升不太清楚。 - Dom045
是的,没错。在“signed int”和“unsigned int”的情况下,结果是无符号的,因此是正数。稍后我会扩展我的答案,以使其更清晰明了。 - Mysticial
显示剩余2条评论

2
< p > printf("promoted\n"); 从未运行的原因是,b*a 总是等于 -128,这比 1 小。 < /p >
a       b       
0x80 * 0x01 = -128 * 1

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