目录
1. 结构体(Struct)
1.1 C++ 结构体和 C 语言结构体的区别
1.2 结构体的对齐方式
2. 联合体(Union)
2.1 联合体特性
3. 结构体和联合体的区别
1. 结构体(Struct)
在 C 语言中,结构体是一种自定义的复合数据类型,允许将不同数据类型的变量组合成一个单一的实体。结构体可以包含多个成员,每个成员可以是不同的数据类型,如整数、浮点数、字符、数组等。
结构体的定义通常在函数外部,并且在函数内部可以声明和使用结构体类型的变量。结构体的定义包含了结构体的名称和结构体成员的列表,每个成员都有一个名称和一个数据类型。结构体的成员可以通过成员运算符(.)来访问。
以下是一个简单的 C语言 结构体的示例:
#include <stdio.h>
// 定义一个名为Student的结构体
struct Student {
int roll_no; // 学号
char name[50]; // 姓名
int age; // 年龄
float score; // 分数
};
int main() {
// 声明并初始化一个Student类型的结构体变量
struct Student student1 = {101, "Alice", 20, 95.5};
// 访问结构体成员并输出
printf("Roll No: %d\n", student1.roll_no);
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("Score: %.2f\n", student1.score);
return 0;
}
1.1 C++ 结构体和 C 语言结构体的区别
C++ 中的结构体和 C 语言中的结构体在语法上基本上是一致的,但在 C++ 中,结构体还具有类的特性,包括封装、继承和多态等,从而与 C 语言中的结构体有一些区别。
主要区别如下:
- 成员函数:C 的结构体内不允许有函数存在,C++ 中的结构体可以包含成员函数,且允许该函数是虚函数,这是与 C 语言中的结构体最大的不同之一。C++ 中的结构体可以像类一样定义成员函数,可以在结构体内部绑定成员函数的实现,并在结构体对象上调用这些成员函数。
- 访问控制:C++ 中的结构体可以使用 public、protected、private 关键字来限制成员变量的访问权限,从而实现封装性;而 C 语言中的结构体对内部成员变量的访问权限只能是 public,可以在任何地方被访问。
- 继承:C++ 中的结构体可以通过继承从其他结构体或派生类,从而实现继承的特性,包括单继承和多继承;而 C 语言中的结构体没有继承的概念。
- 构造函数和析构函数:C++ 中的结构体可以定义构造函数和析构函数,用于对象的初始化和清理操作;C 语言中的结构体没有构造函数和析构函数的概念。
- 默认访问修饰符:C++ 中的结构体成员默认是 private 访问修饰符,而 C 语言中的结构体成员默认是 public 访问修饰符。
- C 中使用结构体需要加上 struct 关键字,或者对结构体使用 typedef 取别名,而 C++ 中可以省略 struct 关键字直接使用.
1.2 结构体的对齐方式
结构体对齐根据最大类型长度对齐。结构体大小一定是最大成员的整数倍。
对齐规则:
- 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐摸数。
- 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍;
如有需要编译器在成员之间加上填充字节作为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员大小的整数倍,若是,则存放本成员,反之,则在成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
- 结构体的总大小为结构体最宽基本类型成员大小的整数倍;
如有需要编译器会在最末一个成员之后加上填充字节,结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。
例如:
//1.
struct A
{
char c1; //大小 (char)1 + 3(填充数)
int i; //大小 (int)4
char c2; //大小 (char)1 + 3(填充数)
}
//该结构体对齐数为 4(int),则结构体大小为
//(1 + 3)+ 4 +(1+3)=12
//2.
struct A
{
char c1; //大小 (char)1 + 3(填充数)
int i; //大小 (int)4
char c2; //大小 (char)1
char c3[5]; 大小 (char)1 * 5 + 2(填充数),
//因为是以4对齐,c2为1个字节,还剩3个位置给c3,
//然后c3的最后两个字节位置再开辟下一行,新一行没有满足4,则再加2个填充数。
}
//该结构体对齐数为 4(int),加上一个char类型的数组
//可以看作有5个char类型存入内存中,则结构体大小为:
//(1+3)+ 4 + 1 + 5 + 2 =16
//3.
struct A
{
char c1;//1+3
int i;//4
char c2;//1+7
double c[5];//40
};
//该结构体对齐数为 8(double),加上一个double类型的数组
//可以看作有5个double类型存入内存中,则结构体大小为:
//(1+3)+ 4 + 1 + 7 + (8*5) =56
2. 联合体(Union)
在 C 语言中,联合体是一种特殊的数据结构,可以在内存中共享同一段存储空间来存储不同类型的数据。与结构体类似,联合体也是一种用户自定义的数据类型,可以包含多个不同类型的成员变量。
联合体的定义使用关键字‘union’,后面紧跟联合体的名称和一对花括号,括号中定义了联合体的成员变量,每个成员变量有自己的名称和数据类型。
#include <stdio.h>
// 定义一个联合体
union Data {
int i;
float f;
char c;
};
int main() {
union Data data; // 声明一个联合体变量data
data.i = 42; // 给联合体的整数成员赋值
printf("data.i = %d\n", data.i); // 输出整数成员的值
data.f = 3.14; // 给联合体的浮点数成员赋值
printf("data.f = %.2f\n", data.f); // 输出浮点数成员的值
data.c = 'A'; // 给联合体的字符成员赋值
printf("data.c = %c\n", data.c); // 输出字符成员的值
// 注意:联合体的不同成员共享同一块内存空间,赋值一个成员会影响其他成员的值
printf("data.i = %d, data.f = %.2f, data.c = %c\n", data.i,data.f, data.c);
//data.i = 1078523201, data.f = 3.14, data.c = A
return 0;
}
2.1 联合体特性
- 联合体是一个结构;
- 它的所有成员相对于基地址的偏移量都为 0 ;
- 次结构空间要大到足够容纳最“宽”的成员;
- 其对齐方式要适合其中所有的成员;
3. 结构体和联合体的区别
(1)结构体中的每个成员都占用独立的内存空间,而联合体中的所有成员共享同一块内存空间。这意味着,在联合体中只有一个成员变量能够同时存储值,而其他成员变量会被覆盖;
(2)结构体的内存占用大小等于所有成员的内存大小之和,而联合体的内存占用大小等于其最大成员的内存大小,因此,联合体在内存占用上通常比结构体更节省;
(3)结构体的成员可以同时被访问和修改,而联合体的成员只能同时访问和修改一个成员。这是因为联合体的成员共享同一块内存空间,修改其中一个成员会影响其他成员的值。
(4)结构体的成员在内存中按照定义的顺序依次排列,而联合体的所有成员共享同一块内存空间,因此只有一个成员可以存储有效值;
(5)结构体的初始化可以为每个成员分别赋值,而联合体的初始化只能对其中一个成员赋值。文章来源:https://www.toymoban.com/news/detail-728335.html
文章来源地址https://www.toymoban.com/news/detail-728335.html
到了这里,关于【基础知识】结构体(struct)和联合体(union)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!