C 无符号整数、浮点数据类型和乘法的古怪

C 无符号整数、浮点数据类型和乘法的古怪,c,unsigned,unsigned-integer,C,Unsigned,Unsigned Integer,我不是很擅长C语言,只是遇到了一个我不懂的问题。代码是: int main() { unsigned int a = 100; unsigned int b = 200; float c = 2; int result_i; unsigned int result_u; float result_f; result_i = (a - b)*2; result_u = (a - b); result_f = (a-b)*c

我不是很擅长C语言,只是遇到了一个我不懂的问题。代码是:

int main()
{
    unsigned int a = 100;
    unsigned int b = 200;
    float c = 2;

    int result_i;
    unsigned int result_u;
    float result_f;

    result_i = (a - b)*2;
    result_u = (a - b);
    result_f = (a-b)*c;

    printf("%d\n", result_i);
    printf("%d\n", result_u);
    printf("%f\n", result_f);
    return 0;
}
输出为:

-200
-100
8589934592.000000
Program ended with exit code: 0
对于(a-b)是负数,而a,b是无符号整数类型,则(a-b)是平凡的。乘以浮点数c后,结果为8589934592.000000。我有两个问题:

首先,为什么将整数类型编号2相乘并分配给整数类型编号后的结果是非平凡的

第二,为什么即使(a-b)是负数并且结果是无符号整数类型,结果仍然是非平凡的

我正在使用Xcode测试这段代码,编译器是默认的APPLE LLVM 6.0


谢谢

您在printf中得到负数,因为您要求它打印一个带有%d的有符号整数。如果要查看最终得到的实际值,请使用%u。这还将向您展示如何得到浮点乘法的输出

你认为
a-b
为负值的假设是完全错误的

由于
a
b
具有
unsigned int
类型,因此使用这两个变量的所有算术运算都在
unsigned int
类型的域中执行。这同样适用于混合“
unsigned int
”算法和
int
”算法。此类操作实现模运算,模等于
UINT\u MAX+1

这意味着表达式
a-b
生成类型为
unsigned int
的结果。它是一个大的正值,等于
UINT_MAX+1-100
。在具有32位
int
的典型平台上,它是
4294967296-100=4294967196

表达式
(a-b)*2也会生成类型为
无符号int
的结果。它也是一个很大的正值(
UINT_MAX+1-100
乘以
2
,取模
UINT_MAX+1
)。在典型的平台上,它是
4294967096

后一个值对于类型
int
太大。这意味着当您将其强制放入变量
result\u i
时,会发生有符号整数溢出。赋值时有符号整数溢出的结果由实现定义。在您的情况下,
result\u i
最终为
-200
。它看起来“正确”,但语言不能保证这一点。(尽管您的实现可能会保证这一点。)

变量
result\u
接收正确的无符号结果-正值
UINT\u MAX+1-100
。但是您可以使用
printf
中的
%d
格式说明符打印该结果,而不是使用正确的
%u
。使用
%d
说明符打印不符合
int
范围的
无符号int
值是非法的。因此,代码的行为未定义。您在输出中看到的
-100
值只是未定义行为的一种表现。这个输出在形式上是没有意义的,即使它乍一看是“正确的”

最后,变量
result\u f
接收
(a-b)*c
表达式的“正确”结果,因为乘法是在
float
域中执行的,因此计算时不会溢出。您看到的是我上面提到的大正值乘以
2
。但它很可能被四舍五入到
float
类型的精度,这是实现定义的。准确的值应该是
4294967196*2=8589934392


有人可能会争辩说,您打印的最后一个值是唯一正确反映无符号算术特性的值,即它“自然”来自
a-b

的实际结果。您能描述一下您所说的“非平凡”是什么意思吗?
printf(“%d\n”,result\u)-->
printf(“%u\n”,结果)%f
打印浮点。它将显示无符号int结果的正确值,这使%f printf的输出变得明显。非常感谢!在表达式(a-b)*2中,2是否也自动视为无符号整数?是因为a,b是未签名的int吗?@facebook-1536745818;是。@facebook-1536745818:正式地说,
2
是一个
int
。但是,当您混合使用大小相同的有符号类型和无符号类型时,无符号类型将“获胜”,并且计算将在无符号类型的域中执行。因此,是的,
2
被解释为无符号。