结构体
- 结构体类型的存储区里包含多个子存储区,每个子存储区可以用来记录对应的信息
- 子存储区(成员变量)可以是不同的数据类型,也可以是结构体类型的
- 结构体声明语句用来创建结构体类型,需要使用
struct
关键字- 结构体类型名称由关键字
struct
和结构体名称一起构成
- 结构体类型名称由关键字
- 结构体成员变量声明语句不会分配内存,只是用来表示存储区的类型和名称
- C语言结构体中不可以包含函数
- 结构体类型可以在头文件里声明
- 结构体作为数据类型定义变量时,这种变量叫做结构体变量,变量会被分配内存,可以存储数据
typedef关键字
typedef
关键字可以用来给数据类型起别名,别名可以提到原来的类型名称使用
/*声明结构体数据类型*/
struct student{
int age;
char name[32];
};
/*定义结构体数据类型变量*/
struct student stu1 = {"18","liming"};
/*struct student相当于int的作用,可以使用typedef给struct student起个别名*/
typedef struct student Student;
Student stu2; //相当于strust student stu2;
stu2.age = 18;
strcpy(stu2.name,"lisi");//需要include <string.h>
printf("age:%d\nname:%s\n",stu2.age,stu2.name);
/*输出结果
cwork$./a.out
age:18
name:lisi
*/
typedef unsigned int u32; //给unsigned int起一个别名u32
typedef struct _PERSON{
char name[64];
int age;
}Person; //给struct _PERSON起一个别名Person
void test(){
u32 val; //相当于 unsigned int val;
Person person; //相当于 struct PERSON person;
}
结构体和函数
- 结构体作为参数
- 可以直接使用结构体类型作为参数向函数中传递数据
- 直接使用结构体类型的形式参数就会造成时间和空间的浪费
- 使用结构体指针类型的形式参数可以避免这种浪费
- 使用结构体指针作为形式参数的适合尽量使用
const
关键字声明
- 可以直接使用结构体类型作为参数向函数中传递数据
- 结构体作为返回值
- 可以把结构体类型的变量直接作为返回值使用,这样可以从被调用函数向调用函数传递结构体数据
- 函数的调用过程会发生结构体内容的复制,更会造成时间和空间上的狼覅额
- 使用结构体存储区的地址作为返回值可以避免这个问题
- 不可以把非静态局部结构体存储区的地址作为返回值使用,因为函数执行完成后,其中的局部变量就释放了
- 可以把结构体类型的变量直接作为返回值使用,这样可以从被调用函数向调用函数传递结构体数据
内存对齐补齐
C语言中的内存对齐(Memory Alignment)是指在内存中分配数据时,将数据放置在特定的地址上,以使得数据的访问更加高效。对齐的规则通常取决于所使用的硬件架构和编译器。
对齐的原因
- 提高数据访问速度:许多处理器在访问未对齐的内存时效率较低。对齐的数据可以使得处理器一次访问所需的数据,从而提高性能。
- 防止硬件异常:某些处理器在访问未对齐的内存时可能会产生硬件异常或错误。
补齐(Padding)是在结构体或数组等复合数据类型中,为了实现对齐而在数据成员之间或数据成员之后插入的额外字节。补齐通常发生在数据成员的大小和其对齐要求不匹配的情况下。
例如,考虑以下C语言的结构体:
struct Example {
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
};
假设我们的系统要求 int
类型数据必须 4 字节对齐,那么编译器可能会在 char a
后面插入 3 个字节的补齐,以确保 int b
从 4 字节边界开始。同样地,编译器也可能在 int b
和 short c
之间插入 2 个字节的补齐,以确保 short c
从 2 字节边界开始。因此,整个 struct Example
的大小可能大于其数据成员大小的总和。
为了避免不必要的内存浪费,程序员通常需要了解其所使用的硬件和编译器的对齐规则,并据此设计数据结构。在某些情况下,可以使用编译器指令或特性来控制对齐行为。
#pragma pack(2)
,结构体的有效对齐值为pack(n)
指定和最大成员长度中较小者;
联合体
- 联合也是用来创建新的数据类型
- 联合类型需要先声明才能使用
- 声明联合类型使用
union
关键字 - 联合成员变量对应的存储区在内存里互相重叠
- 联合成员变量开始的地址都一样
- 联合变量的大小就是它占用空间最大的成员变量大小
- 联合变量可以当作多种不同类型变量使用
#include<stdio.h>
int main(){
typedef union{
char a;
short b;
int c;
}A_t;
A_t data = {.c = 0x12345678};
printf("0x%hhd",data.a); //输出0x78
printf("0x%hd",data.b); //0x5678
printf("0x%d",data.c); //0x12345678
return 0;
}
/*数据传输,计算机接收和发送数据*/
union msg{
unsigned char msg[48];
struct cmd{
unsigned char head[4];
unsigned char data[40];
unsigned char tail[4];
}cmd_info;
}
/*可以用msg来接收数据,然后用cmd_info来读取数据*/
枚举
枚举是一个有限整型常量的列表,每个枚举值都是一个符号常量
默认从0开始,向后依次加一
enum COLOR{RED , GREEN , BLUE , YELLOW};
printf("%d,%d,%d,%d\n",RED,GREEN,BLUE,YELLOW);
/*输出结果为0,1,2,3*/
可以通过赋值改变枚举的值,没有赋值的枚举值 = 前一个枚举值 + 1
enum COLOR{RED , GREEN = 200 , BLUE , YELLOW};
printf("%d,%d,%d,%d\n",RED,GREEN,BLUE,YELLOW);
/*输出结果为0,200,201,202*/
枚举的作用是提高代码可读性
标签:struct,int,联合体,char,对齐,变量,结构 From: https://www.cnblogs.com/one-ten/p/18590586