C语言的各种数据结构所占的字节数

本文详细介绍了不同编译器环境下各种基本数据类型的内存占用情况,包括char、int、float等,并探讨了指针长度及结构体大小的影响因素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

和机器字长及编译器有关系: 
所以,int,long int,short int的宽度都可能随编译器而异。但有几条铁定的原则(ANSI/ISO制订的): 
1 sizeof(short int)<=sizeof(int) 
2 sizeof(int)<=sizeof(long int) 
3 short int至少应为16位(2字节) 
4 long int至少应为32位。

unsigned 是无符号的意思。

例如: 
16位编译器 
char :1个字节 
char*(即指针变量): 2个字节 
short int : 2个字节 
int: 2个字节 
unsigned int : 2个字节 
float: 4个字节 
double: 8个字节 
long: 4个字节 
long long: 8个字节 
unsigned long: 4个字节

32位编译器

char :1个字节 
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器) 
short int : 2个字节 
int: 4个字节 
unsigned int : 4个字节 
float: 4个字节 
double: 8个字节 
long: 4个字节 
long long: 8个字节 
unsigned long: 4个字节

64位编译器 
char :1个字节 
char*(即指针变量): 8个字节 
short int : 2个字节 
int: 4个字节 
unsigned int : 4个字节 
float: 4个字节 
double: 8个字节 
long: 8个字节 
long long: 8个字节 
unsigned long: 8个字节

注意: 
1.singned和unsingned所占字节是相同的

2.格式字符 意义 
d 以十进制形式输出带符号整数(正数不输出符号) 
o 以八进制形式输出无符号整数(不输出前缀0) 
x,X 以十六进制形式输出无符号整数(不输出前缀Ox) 
u 以十进制形式输出无符号整数 
f 以小数形式输出单、双精度实数 
e,E 以指数形式输出单、双精度实数 
g,G 以%f或%e中较短的输出宽度输出单、双精度实数 
c 输出单个字符 
s 输出字符串 
zu 输出无符号10进制整数

3.指针的长度取决于使用的机器和编译器,例如:在现代windows上,指针是32位或是64位长

4.关于结构体的大小: 
结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体: 
struct stu1 

int i; 
char c; 
int j; 
}; 
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成 
员的偏移量加上最后一个成员的大 
小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个 
成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。 
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 二、结构体大小必须是所有成员大小的整数倍。 
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。 
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。 
再看一个满足第一条,不满足第二条的情况 
struct stu2 

int k; 
short t; 
}; 
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编 
译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。 
由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小。对比下面两种定义顺序 
struct stu3 

char c1; 
int i; 
char c2; 

struct stu4 

char c1; 
char c2; 
int i; 

虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。 
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?只需把其展开即可。但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。看下面的例子: 
struct stu5 

short i; 
struct 

char c; 
int j; 
} ss; 
int k; 

结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。 
如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的GCC。其他平台的C编译器可能会有不同的处理。

<think>好的,用户想了解C语言中不同数据类型的字节大小、存储方式和读取方法。首先,我需要整理C语言的基本数据类型及其对应的字节数。根据引用[2],常见的类型包括char(1字节)、short(2)、int(4)、long(4或8)、long long(8)、float(4)、double(8)等。需要注意的是,不同编译器和系统下可能会有差异,比如long类型在32位和64位系统中可能不同。 接下来是存储方式。用户提到了大小端模式,这在引用[1]和[4]中有详细说明。大端是高位字节在前,小端是低位字节在前。例如,int 0x12345678在大端下存储为12 34 56 78,而小端则是78 56 34 12。需要解释这两种模式的区别以及它们对多字节数据类型存储的影响。 然后是读取方法。引用[3]提到了使用fscanf等函数进行文件操作,但这里可能更关注如何从内存中读取不同数据类型的数据。例如,通过指针类型转换来访问特定类型的值,比如将char指针转换为int指针读取整型数据。同时需要注意对齐问题,不同数据类型可能有不同的对齐要求,影响内存访问效率。 比较部分需要总结不同数据类型的特点,比如数值范围、精度、存储效率等。例如,char适合存储字符但范围有限,int适合整数运算,float和double用于浮点数但有精度差异。此外,还要考虑不同场景下的选择,如内存紧张时使用较小类型,需要高精度时使用double。 用户可能的问题包括如何检测当前系统的大小端模式,不同数据类型的取值范围如何计算,以及类型转换时的注意事项。这些问题需要在相关部分提及,并给出示例或解决方法。 最后,确保回答符合格式要求,行内公式用$,独立公式用$$,正确引用来源。同时生成的相关问题要围绕数据类型、存储和读取展开,帮助用户深入理解。</think>### C语言数据类型详解 #### 一、数据类型与字节大小 C语言常见数据类型及其字节大小如下: 1. **基本类型**: - `char`:1字节(字符型) - `short`:2字节(短整型) - `int`:4字节(整型) - `long`:4字节(32位系统)或8字节(64位系统) - `long long`:8字节(长长整型) - `float`:4字节(单精度浮点型) - `double`:8字节(双精度浮点型)[^2] 2. **特殊类型**: - 指针类型:4字节(32位系统)或8字节(64位系统) - 枚举类型(`enum`):与`int`大小相同 - `void`:无大小,仅用于函数返回值和指针 > 注意:字节大小可能因编译器和系统架构不同而有所差异。可通过`sizeof()`运算符验证具体环境中的值,例如: > ```c > printf("int size: %zu\n", sizeof(int)); // 输出4或8 > ``` --- #### 二、存储方式 1. **内存对齐**: 数据在内存中按特定规则对齐以提升访问效率。例如: - `int`(4字节)通常按4字节对齐 - `double`(8字节)按8字节对齐 2. **字节序(大小端模式)**: - **大端模式**(Big Endian):高位字节存储在低地址,如`0x12345678`存储为`12 34 56 78`[^1] - **小端模式**(Little Endian):低位字节存储在低地址,如`0x12345678`存储为`78 56 34 12`[^4] 可通过以下代码检测系统字节序: ```c int num = 0x12345678; char *p = (char *)# if (*p == 0x78) printf("Little Endian"); ``` 3. **浮点数存储**: - 采用IEEE 754标准,例如`float`的存储结构为: $$ (-1)^s \times (1 + \text{尾数}) \times 2^{\text{指数}-127} $$ 其中`s`为符号位,尾数23位,指数8位 --- #### 三、数据读取方法 1. **直接内存访问**: ```c int a = 10; char *ptr = (char *)&a; // 按字节访问整型数据 ``` 2. **文件读取**: - 使用`fread`按数据类型读取二进制文件: ```c FILE *fp = fopen("data.bin", "rb"); int arr[10]; fread(arr, sizeof(int), 10, fp); // 读取10个int类型数据 ``` - 使用`fscanf`格式化读取文本文件: ```c int num; fscanf(fp, "%d", &num); // 读取整型数据[^3] ``` 3. **类型转换**: - 显式转换:`double d = (double)10;` - 隐式转换:`int a = 3.14;`(自动截断为3) --- #### 四、数据类型比较 | 数据类型 | 字节数 | 数值范围(示例) | 适用场景 | |-----------|--------|------------------------|------------------------| | `char` | 1 | -128~127 | ASCII字符存储 | | `short` | 2 | -32768~32767 | 节省空间的整数存储 | | `int` | 4 | -2³¹~2³¹-1 | 通用整数运算 | | `float` | 4 | ±3.4e-38~3.4e38 | 单精度浮点计算 | | `double` | 8 | ±1.7e-308~1.7e308 | 高精度科学计算 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值