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

为何C语言中左移24位会改变unsigned long的取值?

C语言中无符号长整型移位赋值与字面量比较不符的问题解析

问题现象

原本预期0b11010010 << 24与0b11010010000000000000000000000000取值相同,但将结果存入unsigned long变量后,变量比较结果为0;直接使用字面量比较时结果为1。给字面量添加UL后缀后,问题得到解决。测试环境为Apple clang 14.0.0,目标架构x86_64。

原测试代码

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

int main(){
    unsigned long a = 0b11010010000000000000000000000000; 
    unsigned long b = 0b11010010 << 24;
    bool isTheSame1 = a == b;
    printf("isTheSame1 %d \n",isTheSame1);

    bool isTheSame2 = 0b11010010000000000000000000000000 == (0b11010010 << 24);
    printf("isTheSame2 %d",isTheSame2);
}

原输出结果

isTheSame1 0 
isTheSame2 1

原因分析

问题核心在于C语言字面量的默认类型和有符号整数溢出的行为:

  • 字面量默认类型:二进制字面量0b11010010和0b11010010000000000000000000000000默认被编译器解析为signed int类型(x86_64平台下int为32位)。
  • 移位操作的溢出问题:
    1. 0b11010010作为32位有符号int,值为210,左移24位后得到0xD2000000,该值超过了32位有符号int的最大值(2^31-1=2147483647),触发有符号整数溢出,结果变为负数(十进制-771754880)。
    2. 将这个负数赋值给64位unsigned long时,会按照无符号整数规则转换为一个极大的64位值(18446744072937796736)。
  • 直接赋值的类型转换:0b11010010000000000000000000000000作为32位有符号int是负数,但赋值给unsigned long时,会被解释为无符号的32位值0xD2000000,扩展为64位后是3523215360,与移位转换后的结果完全不同。
  • 字面量直接比较的特殊性:直接比较时,两个操作数都是32位有符号int,值均为0xD2000000(作为负数相等),所以比较结果为1。

解决方案

给所有参与移位运算和赋值的二进制字面量添加UL后缀,明确指定其为unsigned long类型,避免有符号整数溢出和类型转换带来的不一致问题。

更新后的测试代码

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

int main(){
    unsigned long a = 0b11010010000000000000000000000000UL; 
    unsigned long b = 0b11010010UL << 24;
    bool isTheSame1 = a == b;
    printf("isTheSame1 %d \n",isTheSame1);

    bool isTheSame2 = 0b11010010000000000000000000000000UL == (0b11010010UL << 24);
    printf("isTheSame2 %d",isTheSame2);
}

更新后的输出结果

isTheSame1 1 
isTheSame2 1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:46:47