计算机中数的存储与表示

以C语言、Windows 64位环境为例

考虑这样一个问题:数 3510593 在计算机中是如何存储的?(测试代码放到最后)

整数的存储方式

整数在计算机中采用补码形式存储,存储过程如下:

  1. 十进制转二进制:​3510593的二进制原始形式为:1101011001000101000001
  2. 补齐32位:​在32位系统中,需补前导零至32位:​00000000001101011001000101000001
  3. 按字节分割(大端序排列):
    00000000 | 00110101 | 10010001 | 01000001
    
  4. 十六进制表示
    每4位一组转为十六进制:
    0x00 0x35 0x91 0x41(大端序)

小端序的实际存储

在Windows x64(小端序)环境中,低位字节存放在低地址。因此实际内存布局为:

低地址 -> 高地址:0x41 0x91 0x35 0x00

通过 show_int输出的结果 41913500验证了这一点,函数按内存顺序依次打印字节的十六进制值。


浮点数的存储方式

浮点数采用IEEE 754标准,存储过程如下:

  1. 十进制转二进制科学计数法:​3510593 = 1.101011001000101000001 × 2²¹
  2. 拆分三部分
    • 符号位:0(正数)
    • 指数部分:21 + 127(偏移量)= 148 → 二进制 10010100
    • 尾数部分10101100100010100000100(截断至23位)
  3. 完整二进制表示
    0 10010100 10101100100010100000100
    
  4. 按字节分割(大端序排列):
    01001010 | 01010110 | 01000101 | 00000100
    

小端序的实际存储

在Windows x64中,浮点数同样按小端序存储:

低地址 -> 高地址:0x04 0x45 0x56 0x4A

通过 show_float输出的结果 0445564a验证了这一点,与内存顺序一致。


大端序与小端序的奇妙之处

  • 大端序:高位字节存放在低地址,符合人类阅读习惯。
  • 小端序:低位字节存放在低地址,便于计算机处理连续进位。

示例对比

数值 大端序(逻辑顺序) 小端序(内存顺序)
整数3510593 00 35 91 41 41 91 35 00
浮点数3510593 4A 56 45 04 04 45 56 4A

思考

  • 最多有几位连续相同?为什么?(提示:IEEE 754标准
类型 二进制
int 00000000001101011001000101000001
float 0 10010100 10101100100010100000100

测试C语言代码

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
typedef unsigned char *byte_pointer;
typedef unsigned int uint32;
  
void show_bytes(byte_pointer start, size_t len){
    size_t i;
    for(i = 0; i < len; i++){
        printf("%.2x", start[i]);
    }
    printf("\n");
}
void show_int(int x){
    show_bytes((byte_pointer) &x, sizeof(int));
}
void show_float(float x){
    show_bytes((byte_pointer) &x, sizeof(float));

}
void show_pointer(void *x){
    show_bytes((byte_pointer) &x, sizeof(void *));

}
void test_show_bytes(int val){
    int ival = val;
    float fval = (float) ival;
    int *pval = &ival;

    show_int(ival);
    show_float(fval);
    show_pointer(pval);
}

void FuncOutputBin(uint32 value)
{

    char string[32]={0};   //形参类型uint32最大为32位,因此我这里定义了大小为32的字符串数组存放
    itoa(value, string, 2);

    // 补齐32位
    int len = strlen(string);
    printf("库函数得到的二进制为:");
    for(int i = 0; i < 32 - len; i++){
        printf("0");
    }
    printf("%s\r\n",string);

}

int main(){
    //test_show_bytes(12345);
    // int val = 0x87654321;
    // byte_pointer valp = (byte_pointer) &val;
    
    // show_bytes(valp, 1);
    // show_bytes(valp, 2);
    // show_bytes(valp, 3);
    // show_bytes(valp, 4);

    int val = 3510593;
    float valf = (float) val;
  
    show_int(val);
    show_float(valf);
    
    //FuncOutputBin(val);
    //FuncOutputBin(valf);
    return 0;
}

千里之行,始于足下