结构体
在C语言中,结构体其实就是一种自定义数据结构,类似Java中的类。使用关键字struct创建。
- 定义
struct Student {
char name[21];
unsigned int age;
char tel[16];
float scores[3];
char sex;
};
- 声明
int main() {
// 创建变量方式一
struct Student student = {"Lucy", 18, "13912345678", 89.0f, 69.0f, 77.0f, 'F'};
// 二
struct Student student1 = {
.name = "Lucy",
.age = 18,
.tel = "13912345678",
.scores[0] = 89.0f,
.scores[1] = 69.0f,
.scores[2] = 77.0f,
.sex = 'F'
};
// 三
struct Student student2;
// 不能直接这样赋值
// student2.name = "Lucy";
strcpy(student2.name, "Lucy");
student2.age = 18;
strcpy(student2.tel, "13912345678");
student2.scores[0] = 89.0f;
student2.scores[1] = 69.0f;
student2.scores[2] = 77.0f;
student2.sex = 'F';
printf("%s\n", student.name);
return EXIT_SUCCESS;
}
- 结构体大小
结构体大小等于其所有成员变量所占内存大小之和。
struct Person1 {
char arr[2]; // 2
char *p; // 8
short d; // 2
int c; // 4
// long类型在windows上是占4个字节,Mac上是8个字节
long g; // 8
double f; // 8
float h[2]; // 8
} person1;
struct Person2 {
char *p; // 8
double f; // 8
float h[2]; // 8
// long类型在windows上是占4个字节,Mac上是8个字节
long g; // 8
int c; // 4
char arr[2]; // 2
short d; // 2
} person2;
int main() {
printf("%zd\n", sizeof(person1)); // 48
printf("%zd\n", sizeof(person2)); // 40
return EXIT_SUCCESS;
}
为什么Person1与Person2所占的内存大小不一样?因为结构体是根据数据类型进行内存对齐的。如下图
原因是结构体需要根据数据类型进行内存对齐,并且是大端对齐。
所以,定义结构体成员变量时,把大的数据类型写在上面。
- 结构体指针与结构体嵌套
struct Class {
char *className; // 8
char sex; // 4
} clz;
struct Person3 {
char *name; // 8
unsigned int age; // 4
struct Class class;
} person3;
int main() {
printf("%zd\n", sizeof(person3)); // 32
struct Person3 *p = malloc(sizeof(person3));
p->name = malloc(sizeof(char) * 6);
strcpy(p->name, "Hello");
p->age = 18;
p->class.className = malloc(sizeof(clz));
strcpy(p->class.className, "三班");
p->class.sex = 'F';
printf("%s\t%d\t%s\t%s\n", p->name, p->age, p->class.className, p->class.sex == 'F' ? "男" : "女");
if (p->class.className) {
free(p->class.className);
}
if (p->name) {
free(p->name);
}
if (p) {
free(p);
}
return EXIT_SUCCESS;
}
共用体
共用体是一个能在同一个存储空间存储不同类型数据的类型,但每一瞬时只有一种起作用;共用体变量的地址和它的各成员的地址都是同一地址,所以,在存入一个新的成员后,原有的成员的值会被覆盖。
union Bean {
double a;
float b;
int c;
short d;
char e;
} bean;
int main() {
// 共用体所占的内存长度等于其最长成员的长度
printf("%zd\n", sizeof(bean));// 8
bean.a = 10;
bean.c = 2;
// 在共用体中最后一次赋值,它的值为准确的
bean.e = 'C';
printf("%.f\n", bean.a); // 10
printf("%d\n", bean.c); // 67
printf("%c\n", bean.e); // C
return EXIT_SUCCESS;
}
枚举
enum Color {
// 默认从0开始
red, blue, yellow
} color;
int main() {
switch (color) {
case red:
printf("%d\n", red);
break;
case blue:
printf("%d\n", red);
break;
case yellow:
printf("%d\n", red);
break;
}
return EXIT_SUCCESS;
}
typedef
// 给struct Student3起别名stu3
typedef struct Student3 stu3;
struct Student3 {
char *name;
int age;
};
int main() {
// 使用时就可以直接使用别名了
stu3 stu = {.name = "Tom", .age = 18};
return EXIT_SUCCESS;
}