C语言结构体的使用技巧
一、内存对齐
内存对齐是指一个数据类型在内存中存放时,对其地址的要求。简单来说内存对齐就是使得其内存地址是该类型大小的整数倍,例如 double 类型的变量,其内存地址需是 8 的倍数(double 大小为 8 字节)。
内存对齐的主要目的就是满足部分 CPU 对内存读写的要求以及优化 CPU 读取内存的效率。在 ARM架构下,如果读取的内存是非对齐的(例如一个 4 字节的 int 落在一个奇数的内存地址上)则会直接抛出异常。
c
struct Node {
char mark;
int size;
char flag;
};
1
2
3
4
5
2
3
4
5
由于 int 在本机器上占用 4 字节,所以其起始地址必须是 4 的倍数,例如:0x7ffeef361260。所以第一个 char 类型后面会有3 字节的内存空隙。而最后一个 char 类型后会有 3 字节空隙的原因则是遵循另一个原则:结构体的大小为对齐系数的整数倍。在 Linux 平台下,该值通常为 4,所以 Node 的大小必须为 4 的整数倍,故填充了 3 字节的空隙。
不过,我们可以通过调整结构体成员变量的定义顺序,来减少内存空隙,以节省内存:
c
struct Node {
char mark;
char flag;
int size;
};
struct Node {
int size;
char mark;
char flag;
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
上述两种方式得到的 Node 大小均为 8,相较于最初版本节省了 4 字节的内存。所以,结构体中成员变量的顺序将会影响程序使用内存的大小。
二、结构体定义
- 传统的结构体格式定义
c
struct student
{
int id;
char name[32];
int age;
};
1
2
3
4
5
6
7
2
3
4
5
6
7
- 在定义结构的同时定义变量,该变量目前是全局变量
c
struct test
{
int a;
float b;
char c;
}var;
1
2
3
4
5
6
2
3
4
5
6
- //NEW_TYPE == struct abc
c
typedef struct abc
{
int a;
int b;
}NEW_TYPE;
1
2
3
4
5
2
3
4
5
三、访问结构体内的成员
c
struct test
{
int a;
float b;
char c;
}var , *p; //在定义结构的同时定义变量,该变量目前是全局变量
1
2
3
4
5
6
2
3
4
5
6
结构体变量中定义了普通变量var和指针变量p
1、访问var写法:
c
var.a
var.b
var.c
1
2
3
2
3
2、访问指针变量p中元素写法:
c
(*p).a
(*p).b
(*p).c
1
2
3
2
3
3、本来访问格式一样,但为了简洁c语言有了下写法:
c
p->a
p->b
p->c
1
2
3
2
3
4、访问内存地址 例如:
首先你确定这个结构体是多少字节,几字节对齐。-4字节对齐。
正常的访问赋值方法是:
现在换一种方式:
c
int *p1 = (int *)&temp;
1
访问的时候就是
c
*(p) 是访问的temp.sp.STDSP
*(p+1) 是访问的temp.sp.STMSP
*(p+2) 是访问的temp.sum
1
2
3
2
3
四、结构体初始化
这里介绍构造函数
构造函数:就是用来初始化结构体的一种函数,它直接定义在结构体内,它的特点是不需要写返回类型,且函数名也结构体相同。
c
struct studentInfo{
int id;
char gender;
studentInfo(){} //用以不初始化就定义结构体变量
studentInfo(int _id,char _gender): id(_id),gender(_gender){}
}pt;
pt = studentInfo(1,'a');
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
还有就是直接赋值
这里看一个项目中精简的定义赋值方法: