1、首先我们要知道一些变量所占据的内存有多少和字节的换算单位。
(1)1B(字节)= 8位(比特)
(2)1KB(千字节)= 1024(2^9)B(字节)
(3)1MB(兆字节)= 1024KB(千字节)
(4)1GB(吉字节)= 1024MB(兆字节)
(5)1TB(太字节) = 1024GB(吉字节)
2、C语言中变量所占据的内存。
#includeint main() { printf("int=%dn", sizeof(int)); printf("short=%dn", sizeof(short)); printf("char=%dn", sizeof(char)); printf("float=%dn", sizeof(float)); printf("double=%dn", sizeof(double)); printf("int *=%dn", sizeof(int*)); printf("char *=%dn", sizeof(char*)); printf("float *=%dn", sizeof(float*)); printf("double *%dn", sizeof(double*)); return 0; }
我们知道每个变量和它所占的内存后,我们就可以更好的去定义结构体了,首先明确结构体定义的原则:
必须保证结构体字节对齐(两个对齐)。 (1)保证最长字节对齐 (2)保证整数倍地址对齐 例1#includeint main() { typedef struct Student { int a; char c; }Student; printf("%d", sizeof(Student)); return 0; }
如果你不了解结构体的内存分配,你大概率会猜此结构体占内存为5个字节,正确答案:输出结果为8字节,一个整型加一个字符型变量,正常运算的确是5个字节,但是在结构体中存储方式是不同的,如图,在地址空间中a和c是并列的,结构体中也是挨着的,原则中,必须保证最长字节对齐,所以有3个字节是被浪费掉的,总体占据8个字节。
| a | |||
| c | x | x | x |
#includeint main() { typedef struct Student { char a; int b; char c; }Student; printf("%d", sizeof(Student)); return 0; }
一个字符型,两个整型变量,在结构体中要保证最长字节对齐,所以此结构体输出为12字节,空间内存分配如图
| a | x | x | x |
| b | |||
| c | x | x | x |
如图,最长字节对齐,所以每个变量占据4个字节,但是有6字节的空间是被浪费掉的,b的地址在a的后面,c的地址在b的后面,地址是从小到大排列的。
例2改进#includeint main() { typedef struct Student { int a; char b; char c; }Student; printf("%d", sizeof(Student)); return 0; }
如图,输出结果为8字节,三个变量和例1的两个变量内存空间占据相同,空间中内存分配如图:
| a | |||
| b | c | x | x |
最开始的原则中第二条我们说过保证整数倍地址对齐,最后两个字节被浪费,存储的8个位置我们给它地址进行编号,如图储存的变量位置必须是内存的整数倍,也就是说,如果两个占4字节的变量存储,那么都会被占满,或者是四个占2字节的变量,可以完全占用。
| 0 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 |
#includeint main() { typedef struct Student { int a; short b; char c; char d; }Student; printf("%d", sizeof(Student)); return 0; }
结构体中是定义了一个整型,一个短整型,两个字符型变量,以最长的int为标准,可以知道,地址空间中内存长度为4,整体占据内存为8字节。如图:内存没有被浪费。
| a | |||
| b | c | c | |
#includeint main() { typedef struct Student { int a; char b; short c; char d; }Student; printf("%d", sizeof(Student)); return 0; }
结构体中定义了一个整型,一个短整型,两个字符型变量,定义的数量相同,但是因为地址空间的位置不同,它所占据的内存也不是和例3一样的8字节,它是12字节。如图:
| a | |||
| b | x | c | |
| d | x | x | x |
最长的整型变量a占据4个字节,按照原则2,保证整数倍地址对齐,c占两个字节,所以c的位置应该是2的整数倍如果对其进行编号,c的起始地址在6位置,d的位置在c后面,以此类推。
| 0 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 |
#includeint main() { typedef struct Student { int a; long long int b; short c; int d; char e; }Student; printf("%d", sizeof(Student)); return 0; }
long long int 占据内存为8,计算此结构体所占内存为32字节,可以看到,每一行的地址空间最多8字节,第一行a,b地址在a后面,但是占据8个字节,所以第二行b,占据整行,然后第三行c占据2字节,2字节后面,是d占据4字节,最后一行e占1字节,空了七个字节。如图:
| a | x | x | x | x | |||
| b | |||||||
| c | x | x | d | ||||
| e | x | x | x | x | x | x | x |
那么,如何分配才能让它更好利用内存呢?内存为24字节。
| a | |||||||
| b | c | ||||||
| c | e | x | x | x | x | x | |
程序如下:
#include例6int main() { typedef struct Student { long long int a; int b; int c; short d; char e; }Student; printf("%d", sizeof(Student)); return 0; }
#includeint main() { typedef struct Student { char a : 2; char b : 2; char c : 2; char d : 2; }Student; printf("%d", sizeof(Student)); return 0; }
我们定义了4个字符型变量但是这种表示方法,是在硬件编程中常用的,尤其汇编语言中,这四个变量总计占1个字节,8位(看本文开头),a : 2 定义的是两位,占两个比特。
| a | b | c | d |
字符型变量2字节,16位,本结构体中总计1个字节。



