整形数据在内存中的储存

目录

1.数据类型的介绍:

2.整形在内存中的储存方式: 

2.1原码、反码、补码的关系:

         2.2大小端介绍(字节储存的顺序问题

3.加减法运算的问题(数字大小超过类型的上限)

例题1:例题2:例题3:例题4:


1.数据类型的介绍:

char类型的变量在内存中是以ascⅡ的形式储存,所以也是整形家族的一员。


2.整形在内存中的储存方式: 

在计算机中整数有三种二进制的表示方法,即原码,反码,补码

在原码中最高位为符号位,0表示正数,1表示负数。

2.1原码、反码、补码的关系:

正整数的原码、反码、补码不变,都是相同的。

负整数的反码是原码的相反,即0变1,1变0,但符号位不变.

补码是反码加一得到的。

如:-1

  

对于整形在内存中是以补码的方式进行存储。

为什么呢?

因为cpu只有加法器,使用补码,我们能把符号位和数值位统一处理,加法和减法统一处理。

2.2大小端介绍(字节储存的顺序问题)

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地
址中。

问什么会有大小端存储?

应为除啦一个字节的char,其他的整形都是多字节的,这是就会涉及每个字节存放顺序的问题,可以低地址处存放权重低的 ,也可以低字节处存放权重大的。

此处我们用计算机看看字节存放的顺序

可以看处78位于权重低的位置,放在低字节处,12位于权重高的地方位于高字节处。

此处我们用程序判断大小端的问题

大小端储存模式的判断 · 风夏/C语言进阶 - 码云 - 开源中国 (gitee.com)

#include<stdio.h>

int main()
{
	int a = 1;
	char* p = &a;
	if (*p)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}


3.加减法运算的问题(数字大小超过类型的上限)

例题1:

#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf("a=%d,b=%d,c=%d",a,b,c);
    return 0; 
}

char a占一个字节,二进制表示为:

-1占四个字节,在放入char类型时,因为放不下我们会发生截断,我们把最后8个比特位放进去

当它以%d的形式输出时,会发生补位的现象,现在最高位为一,前面就补3个字节的1,让后以%d的形式输出,所以第一个结果为-1,

同理可得第二个结果和第一个一样,第二个结果为-1

第三个当-1的补码放入unsigned char时,由于只有一个字节仍然为8个1;当它以%d的形式输出时,因为是无符号的,直接补0;即第三个结果为255 

例题2:

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0; 
}

-128存放的char中发生截取,后面因为%u的输出,原来a的类型为有符号的char,我们补位时不最高位的数字,即1(补位规则),让后以%u的形式输出,最后结果 

 例题3:

#include <stdio.h>
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0;
}

  char类型变量的大小为-128到127,此时128已超过范围,当128,放进去时会被视为-128,补位时char a是有符号的类型,补最高位的1,最后结果

例题4:

#include <stdio.h>
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0; }

此题于上题类似,unsigned char 最大值为255,当i=256时,会被视为0,重新开始循环。所以此题为死循环

<think>我们正在讨论浮点数转换为整数时内存中的数据变化。根据IEEE 754标准,浮点数在内存中的表示与整数完全不同。浮点数通常由符号位、指数部分和尾数部分组成,而整数则是直接以二进制补码形式表示(对于有符号整数)。 当我们将一个浮点数转换为整数时,计算机会执行以下步骤: 1. 检查浮点数是否在目标整数类型的表示范围内。如果超出范围,行为可能是未定义的(如C/C++)或抛出异常(如Java)或返回边界值(如Python)。 2. 如果浮点数在范围内,则截断小数部分(向零取整)得到整数值。 3. 将该整数值按照目标整数类型的二进制表示形式存储。 内存变化: 浮点数的内存布局(以32位单精度为例): - 1位符号位(S) - 8位指数位(E) - 23位尾数位(M) 整数的内存布局(以32位有符号整数为例): - 直接使用32位二进制补码表示。 因此,转换过程中,内存中的数据会发生根本性的改变。例如,浮点数3.14在内存中的表示与整数3的表示完全不同。 举例说明: 浮点数3.14(单精度)的二进制表示(IEEE 754): 符号位:0(正数) 指数部分:10000000(偏移127,实际指数为128-127=1) 尾数部分:10010001111010111000011(近似表示0.14的二进制小数部分) 整个32位:0 10000000 10010001111010111000011 而整数3的32位二进制补码表示: 00000000 00000000 00000000 00000011 因此,转换后,内存中原来存储浮点数的位模式被完全替换为整数的位模式。 我们还可以参考引用[4]中提到的例子:将11.375转换成IEEE 754浮点数格式,然后再将其转换为整数。整数11的二进制表示与浮点数的二进制表示完全不同。 步骤总结: 1. 浮点数在内存中按照IEEE 754标准存储(以单精度或双精度)。 2. 转换时,计算机会根据浮点数的值计算出对应的整数(去掉小数部分,注意溢出)。 3. 将计算得到的整数按照目标整数类型(如int32, int64等)的二进制补码形式存入内存。 注意:在转换过程中,小数部分会被丢弃(截断),而不是四舍五入。例如,3.9转换为整数会得到3,-3.9转换为整数会得到-3。 另外,引用[3]提到浮点数的小数在转换时可能存在舍入误差,但这里我们讨论的是截断,所以误差仅来自于小数部分的直接丢弃。 下面我们用一个具体的C++代码示例来展示转换过程(注意:这里我们无法直接看到内存变化,但我们可以通过打印内存字节来观察): 假设我们有一个浮点数f = 3.14f,将其转换为整数i = (int)f。 我们可以通过以下方式查看内存表示(示例代码,仅用于说明): ```cpp #include <iostream> #include <iomanip> #include <cstring> int main() { float f = 3.14f; int i = static_cast<int>(f); // 显式转换 // 打印浮点数的内存表示 unsigned char* p_float = reinterpret_cast<unsigned char*>(&f); std::cout << "浮点数内存表示(16进制): "; for (int j = 0; j < sizeof(float); j++) { std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(p_float[j]) << " "; } std::cout << std::endl; // 打印整数的内存表示 unsigned char* p_int = reinterpret_cast<unsigned char*>(&i); std::cout << "整数内存表示(16进制): "; for (int j = 0; j < sizeof(int); j++) { std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(p_int[j]) << " "; } std::cout << std::endl; return 0; } ``` 运行结果(在小端序机器上): 浮点数3.14的表示(单精度):0x4048f5c3(在内存中字节顺序为:c3 f5 48 40,因为小端序) 整数3的表示:0x00000003(在内存中字节顺序为:03 00 00 00) 可以看到,内存中的字节完全不同。 总结:浮点数转整数时,内存中的数据会从浮点数的IEEE 754表示转换为整数的二进制补码表示,且小数部分被截断。 §§相关问题§§ 1. 浮点数转换为整数时,如何处理溢出情况? 2. 为什么浮点数的小数部分在转换时会被截断而不是四舍五入? 3. 能否通过直接复制内存的方式将浮点数转换为整数?为什么? 4. 不同编程语言在浮点数转整数时有哪些差异?</think>### 浮点数转整数的内存数据变化分析 当浮点数转换为整数时,内存中的数据会发生以下本质变化(以32位单精度浮点数转32位整数为例): #### 1. **内存布局重构** 浮点数(IEEE 754标准)和整数的内存结构完全不同: - **浮点内存结构**(4字节): $$ \underbrace{1\ \text{位}}_{\text{符号}} \mid \underbrace{8\ \text{位}}_{\text{指数}} \mid \underbrace{23\ \text{位}}_{\text{尾数}} $$ 例如 `3.14` 的十六进制:`0x4048F5C3` - **整数内存结构**(4字节补码): 直接存储二进制值,例如 `3` 的十六进制:`0x00000003` #### 2. **转换核心步骤** 1. **分离符号与数值** 提取浮点数的符号位(确定正负)和尾数部分(有效数字)。 2. **指数调整** 根据指数位计算实际位移量。例如浮点数 $11.375$: - 整数部分 $11$ 的二进制:$1011_2$(通过引用[4]的除法转换) - 指数值 $E = \text{指数域} - 127$ 3. **截断小数** 直接丢弃小数部分(非四舍五入),例如: ```python # Python示例(引用[1]) int(3.14) # 结果=3,小数部分0.14被丢弃 ``` 4. **补码转换** 将截断后的整数值转为二进制补码: - 正数:原码 = 补码 - 负数:取反加一 #### 3. **内存变化实例** 以浮点数 $11.375$ → 整数 $11$ 为例: | 步骤 | 浮点数表示(IEEE 754) | 整数表示(补码) | |------------------|-----------------------------|-----------------------| | 原始内存 | `0x41360000` (十六进制) | 无效 | | 转换后内存 | 无效 | `0x0000000B` (十六进制)| | 二进制展开 | `0100 0001 0011 0110 0000...` | `0000 0000 0000 1011` | > 💡 关键区别:浮点数的指数/尾数结构被完全替换为整数的线性二进制值。 #### 4. **特殊场景处理** - **溢出处理**(如 $10^{20}$ 转 int) 超出整数范围时: - C++:未定义行为(引用[2]) - Java/Python:保留低位或报错(引用[3]) - **精度损失** 浮点小数无法精确存储(引用[3]): $$ 0.1 + 0.2 \neq 0.3 \quad \text{(二进制舍入误差)} $$ #### 5. **验证代码(C++)** ```cpp #include <iostream> #include <bitset> int main() { float f = 11.375f; int i = static_cast<int>(f); // 显式转换(引用[2]) // 打印内存数据 std::cout << "浮点数内存: " << std::bitset<32>(*(int*)&f) << "\n"; // 二进制展开 std::cout << "整数内存: " << std::bitset<32>(i) << "\n"; return 0; } ``` **输出**: ``` 浮点数内存: 01000001001101100000000000000000 整数内存: 00000000000000000000000000001011 ``` ### 总结 浮点数转整数的本质是**内存数据的完全重构**: 1. IEEE 754的三段式结构被破坏 2. 新内存写入整数补码 3. 小数部分被不可逆丢弃 4. 符号和整数值得以保留 此过程解释了为什么直接内存复制(如`memcpy`)无法实现正确转换[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值