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

为何char与short类型数据会被存储在4字节寄存器中?

为什么char/short类型数据会被存入4字节寄存器?

背景信息

  • 正在学习将C代码转换为汇编代码,发现char和short类型的数据会被存储在4字节寄存器中
  • 编译参数:-Og -g,通过gdb的disas main命令查看汇编,运行环境为64位系统

示例C代码

#include <stdio.h>

int main(void) {
    const int LEN = 3;
    char c[LEN];
    c[0] = 1;
    c[1] = 2;
    c[2] = 3;

    for(int i = 0; i < LEN; i ++) {
        printf("%d\n", c[i]);
    }

    return 0;
}

对应部分反汇编代码

0x000000000000116e <+5>:     sub    $0x10,%rsp
   0x0000000000001172 <+9>:     mov    %fs:0x28,%rax
   0x000000000000117b <+18>:    mov    %rax,0x8(%rsp)
   0x0000000000001180 <+23>:    xor    %eax,%eax
   0x0000000000001182 <+25>:    movb   $0x1,0x5(%rsp)
   0x0000000000001187 <+30>:    movb   $0x2,0x6(%rsp)
   0x000000000000118c <+35>:    movb   $0x3,0x7(%rsp)
   0x0000000000001191 <+40>:    mov    $0x0,%ebx
   0x0000000000001196 <+45>:    jmp    0x11b9 <main+80>
   0x0000000000001198 <+47>:    movslq %ebx,%rax

   # why %edx?
   0x000000000000119b <+50>:    movsbl 0x5(%rsp,%rax,1),%edx


   0x00000000000011a0 <+55>:    lea    0xe5d(%rip),%rsi        # 0x2004
   0x00000000000011a7 <+62>:    mov    $0x1,%edi
   0x00000000000011ac <+67>:    mov    $0x0,%eax
   0x00000000000011b1 <+72>:    callq  0x1070 <__printf_chk@plt>
   0x00000000000011b6 <+77>:    add    $0x1,%ebx
   0x00000000000011b9 <+80>:    cmp    $0x2,%ebx
   0x00000000000011bc <+83>:    jle    0x1198 <main+47>

疑问与关联思考

了解Java中byte、char或short会被提升为int,不确定这是否与此问题相关。


解答

这一现象是C语言整数提升规则与x86-64调用约定共同作用的结果,和Java的类型提升本质逻辑一致:

  1. C语言的整数提升规则
    在表达式计算、函数参数传递等场景中,char、short(包括有符号和无符号版本)会被自动提升为int类型——只要int能够容纳原类型的所有取值(在绝大多数系统中,int是4字节,完全覆盖1字节char和2字节short的取值范围)。这一规则是为了简化不同小整数类型之间的运算逻辑,避免额外的类型转换开销。

  2. 汇编层面的具体体现

    • 存储阶段:从反汇编的movb指令可以看到,char类型数据确实是以1字节的形式存储在栈上(写入0x5(%rsp)等单字节地址)。
    • 读取与传递阶段:movsbl指令的作用是将单字节的有符号char符号扩展为4字节的int,然后存入32位寄存器%edx中。这是因为printf的%d格式符期望接收int类型的参数,而按照x86-64的System V调用约定,整数参数会通过寄存器传递,%edx对应第三个参数的位置(前两个参数分别是__printf_chk的flag和格式串地址)。
    • 64位系统的寄存器特性:在x86-64模式下,写入32位寄存器会自动将对应64位寄存器的高32位清零,因此%edx中的4字节int值会被正确扩展为64位,符合调用约定的要求。
  3. 与Java类型提升的关联
    Java中byte、char、short提升为int的设计,本质和C的整数提升是相同的思路——使用通用的int类型作为小整数运算的默认类型,减少类型转换的复杂度和性能开销。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:06:29