今天给小伙伴们分享的是数据在内存中存储的相关知识,全程干货满满哦~
一.基本类型的介绍
在C语言中,基本内置类型及其通常的内存大小如下。但请注意,实际的大小取决于编译器和正在运行程序的系统的架构(32位或64位)。
-
整数类型:
int
: 通常为 4 字节,但有时在某些系统上可能是 2 字节。char
: 总是为 1 字节。short
: 至少为 2 字节,通常是 2 字节。long
: 至少为 4 字节,32位系统上通常是 4 字节,64位系统上可能是 8 字节。long long
: 至少为 8 字节。
-
浮点类型:
float
: 通常是 4 字节(单精度)。double
: 通常是 8 字节(双精度)。long double
: 至少为 12 字节,但可能更大。
-
无符号类型:
unsigned int
: 与int
相同。unsigned char
: 与char
相同。unsigned short
: 与short
相同。unsigned long
: 与long
相同。unsigned long long
: 与long long
相同。
-
布尔类型 (C99 标准引入):
bool
: 通常为 1 字节。_Bool
: 至少为 1 字节。
-
_Complex 类型 (C99 标准引入):
complex
: 由两个float
类型的值组成,因此通常是 8 字节。double _Complex
: 由两个double
类型的值组成,因此通常是 16 字节。
-
void 类型:
void
: 没有内存大小。
-
指针类型:
- 指针的大小取决于系统的架构:
- 在32位系统上,指针通常是 4 字节。
- 在64位系统上,指针通常是 8 字节。
- 指针的大小取决于系统的架构:
-
枚举类型 (
enum
):enum
: 大小取决于底层的表示类型,但至少与int
相同。
-
结构体类型 (
struct
):struct
: 大小取决于其成员的排列和对齐。
-
联合类型 (
union
):union
: 大小等于其最大成员的大小。
-
数组类型:
- 数组的大小是其元素大小乘以元素数量。
要确定特定系统上特定类型的确切大小,可以使用 sizeof
运算符。
二. 原码、反码、补码
一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型而决定的。 那么数据在所开辟内存中到底是如何存储的呢? 这里就得引出 原码 、反码和补码了, 整型的存储 与它们息息相关。在计算机科学中,原码、反码和补码是用于表示有符号整数的不同二进制编码方式。这些编码方式在计算机系统中用于简化算术运算,尤其是在处理负数时。以下是每种编码方式的详细解释:
-
原码(True Form):
- 原码是最直观的表示方法,其中最高位用作符号位(0表示正数,1表示负数),其余位表示数值的绝对值。
- 例如,对于一个8位的整数,
0010 0101
(原码)表示正数3,而1010 0101
(原码)表示负数3。
-
反码(One's Complement):
- 反码用于表示负数的另一种形式。对于正数,其反码与原码相同;对于负数,反码是其原码除符号位外,其他各位取反(即0变1,1变0)。
- 例如,
0010 0101
(反码)表示正数3,而1111 1010
(反码)表示负数3。
-
补码(Two's Complement):
- 补码是计算机中最常用的表示方法,用于简化二进制的加法和减法运算。对于正数,其补码与原码相同;对于负数,补码是其反码加1。
- 补码的设计允许计算机使用相同的加法运算来处理加法和减法,因为负数的补码可以通过加1得到正数的补码。
- 例如,
0010 0101
(补码)表示正数3,而1111 1011
(补码)表示负数3。
特点和用途:
- 原码:直观,但不利于计算机处理。
- 反码:用于表示负数的一种方式,但不是计算机中常用的表示方法。
- 补码:计算机中最常用的表示方法,因为它允许使用相同的硬件电路来处理加法和减法。
示例:
假设我们有一个8位的整数,数值为3和-3:
-
原码:
- 正数3:
0010 0101
- 负数3:
1010 0101
- 正数3:
-
反码:
- 正数3:
0010 0101
- 负数3:
1111 1010
- 正数3:
-
补码:
- 正数3:
0010 0101
- 负数3:
1111 1011
- 正数3:
在计算机系统中,通常使用补码来表示整数,因为它简化了算术运算的硬件实现。
三.大小端介绍
大小端(Endianness)是指计算机系统中字节(Byte)的排列顺序。在多字节数据(如整数、浮点数等)的存储中,不同的计算机系统可能会以不同的方式排列字节的顺序。主要有两种大小端模式:
-
大端(Big-Endian):
- 在大端模式中,最重要的字节(最高有效字节,即MSB)存储在最低的内存地址处,其次是次高有效字节,以此类推,直到最低有效字节(LSB)存储在最高的内存地址处。
- 例如,假设有一个16位的整数
0x1234
,它在大端模式下的内存存储顺序为0x12 0x34
。
-
小端(Little-Endian):
- 在小端模式中,最低有效字节(LSB)存储在最低的内存地址处,然后是次低有效字节,以此类推,直到最高有效字节(MSB)存储在最高的内存地址处。
- 同样以
0x1234
为例,它在小端模式下的内存存储顺序为0x34 0x12
。
影响:
大小端模式的不同会影响数据在网络上的传输以及不同系统间的文件交换。例如,网络协议通常规定以大端模式传输数据,而许多现代的个人电脑和服务器则使用小端模式存储数据。
如何确定系统的类型:
在C语言中,可以通过编写一个简单的程序来确定系统是大端还是小端:
#include <stdio.h>
int main() {
unsigned int x = 0x12345678;
char *c = (char*) &x;
if (*c == 0x78) {
printf("Little-Endian\n");
} else {
printf("Big-Endian\n");
}
return 0;
}
这段代码通过检查一个整数的最低位字节的内容来确定系统的字节序。如果输出是 0x78
,则系统是小端模式;如果输出是 0x12
,则系统是大端模式。
总结
大小端模式是计算机系统设计中的一个基本属性,它影响着数据的存储和传输。了解和处理大小端问题是计算机编程中的一个重要方面。
四.浮点型在内存中的存储
浮点型的存储与整型的存储大大不同。在计算机系统中,浮点数的存储通常遵循特定的标准,以确保不同系统和平台之间浮点数的一致性和可移植性。最常用的标准是 IEEE 754 标准,它定义了浮点数的存储格式、精度和操作。
IEEE 754 标准
IEEE 754 标准有几种不同的格式,包括单精度(32位)、双精度(64位)和扩展精度(80位、128位等)。这里我们主要讨论最常用的单精度和双精度浮点数:
-
单精度浮点数(32位):
- 符号位(1位):最高位是符号位,0 表示正数,1 表示负数。
- 指数位(8位):表示数值的范围,使用偏移量(bias)表示,单精度中 bias = 127。
- 尾数位(或小数位,23位):表示数值的精度,存储实际的数值部分。
-
双精度浮点数(64位):
- 符号位(1位):同样,最高位是符号位。
- 指数位(11位):双精度中的 bias = 1023。
- 尾数位(或小数位,52位):存储实际的数值部分。
存储格式
以单精度为例,一个浮点数 A
在内存中的存储可以分为三个部分:
- 符号位:1位
- 指数:8位
- 尾数:23位
存储格式如下:
SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
S
代表符号位E
代表指数位M
代表尾数位
计算方法
- 指数:存储的指数值需要减去偏移量(bias)来得到实际的指数值。
- 尾数:尾数部分通常在存储时会默认加上一个隐含的前导1(对于规格化数),即
1.MMMMMMMMM
,其中1
是隐含的。
示例
假设有一个单精度浮点数 A = 3.5
,其二进制表示为 11.1
(忽略小数点后的无限循环部分),则:
- 符号位
S
为0
(因为 A 是正数)。 - 指数部分
E
为10000101
,转换为十进制为133
,实际指数为133 - 127 = 6
。 - 尾数部分
M
为10000000000000000000000
。
因此,3.5
的 IEEE 754 表示为:
0 10000101 10000000000000000000000
注意
- 特殊值如
NaN
(非数)、Infinity
(无穷大)和0
(零)有特殊的编码方式。 - 浮点数的表示可能不是唯一的,因为存在规格化和非规格化数的不同表示。
了解浮点数的存储方式对于编写精确的数值计算程序非常重要,尤其是在处理浮点数精度和舍入误差时。
最后祝小伙伴们天天开心,早日成为技术大牛@
标签:存储,反码,字节,浮点数,补码,剖析,内存,原码 From: https://blog.csdn.net/Code_Allen/article/details/142592046