You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言常规算术转换疑问:关系与算术运算类型转换问题

C语言常规算术转换的两个常见疑问解答

问题背景

在学习C语言类型转换中的常规算术转换时,原本认为隐式转换是编译器自动将窄类型提升为宽类型,但通过两个实验产生了疑问:

关系运算符实验

#include <stdio.h>

int main(void){

    unsigned long int a  = 8888;
    unsigned long int c = 0;
    signed int b = -1;

    if(a > b){
        c = 10;
    }else {
        c = 7;
    }
    
    printf("C value is %lu\n",c);
    
}

按数学逻辑,a=8888大于b=-1,c应等于10,但实际运行结果c=7。

算术运算符实验

#include <stdio.h>

int main(void){

    unsigned long int a  = 8888;
    unsigned long int c;
    signed int b = -1;

    c = b + a;
    
    printf("C value is %lu\n",c);
    
}

实际运行结果c=8887,而非预期的大数(如4294976184)。


疑问解答

1. 为何关系运算符a > b的结果不符合预期?

这是因为常规算术转换的核心规则:当有符号类型和无符号类型进行比较或运算时,有符号类型会被转换为对应的无符号类型。

在这个例子里:

  • b是signed int类型的-1,和unsigned long int类型的a比较时,b会被强制转换为unsigned long int类型。
  • 有符号整数-1转换为无符号整数时,会按照无符号类型的取值范围做模运算,结果是该无符号类型的最大值(比如64位系统中,unsigned long int的最大值为18446744073709551615)。
  • 显然8888远小于这个最大值,所以a > b的结果为假,执行else分支,c被赋值为7。

2. 算术运算b + a为何得到8887?

同样是常规算术转换规则导致的结果:

  • 运算前,signed int类型的b=-1被转换为unsigned long int类型,值为该类型的最大值(记为ULONG_MAX)。
  • 执行加法ULONG_MAX + 8888时,会发生无符号整数溢出。无符号整数的溢出是标准定义的合法行为,结果为(ULONG_MAX + 8888) % 2^N(N是unsigned long int的位数,比如64位)。
  • 因为ULONG_MAX = 2^N - 1,所以(2^N -1) + 8888 = 2^N + 8887,模2^N后结果就是8887,和实际运行结果一致。这不是异常溢出,而是无符号整数运算的既定规则。

内容的提问来源于stack exchange,提问作者Vignesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:54:52