目录
1. 概述
数组:连续的相同数据类型的集合
结构体:不同数据类型的集合
2. 定义和初始化
- 先声明结构体类型再定义变量名
- 在声明类型的同时定义变量
- 直接定义结果体类型变量(无类型名)
- 定义结构体类型,再使用该类型定义变量
struct stu {
char name[20];
int age;
};
struct stu s1 = { "lily", 20 };
- 定义结构体类型同时定义变量
struct stu2 {
char name[20];
int age;
} s2 = { "lily", 20 };
- 定义结构体变量,不定义类型
struct{
char name[20];
int age;
} s3 = { "lily", 20 };
3. 成员的使用
- 结构体.成员
- 结构体->成员
# include<stdio.h>
struct stu {
char name[20];
int age;
};
int main() {
struct stu s1 = { "lily", 20 };
// 1. 通过点运算符访问s1变量的成员
printf("名字是:%s\n", s1.name);
// 修改
strcpy(s1.name, "Jorry");
printf("名字是:%s\n", s1.name);
// 2. 通过->运算符访问结构体指针变量p的成员
printf("(&s1)->name = %s, (&s1)-> age = %d\n", (&s1)->name, (&s1)->age);
return 0;
}
4. 结构体数组
# include<stdio.h>
struct stu {
char name[20];
int age;
};
int main() {
struct stu s1[5] = {
{"lily", 24 },
{"lidaly", 205 },
{"lidaly", 203 },
{"lilsady", 230 },
{"lily2", 22 } };
for (int i = 0; i < 5; i++) {
printf("输出%d个:---------\n", i);
printf("名字是:%s, 年龄: %d\n", s1[i].name, s1[i].age);
printf("名字是:%s, 年龄: %d\n", (*(s1+i)).name, s1[i].age);
printf("名字是:%s, 年龄: %d\n", (s1 + i)->name, s1[i].age);
}
printf("-----------");
return 0;
}
5. 结构体套结构体
# include<stdio.h>
struct stu {
char name[20];
int age;
};
struct teacher {
int age;
struct stu s;
};
int main() {
// 这样子写也可以
// struct teacher t[2] = { 40, "张三", 18, 42, "李四", 28};
struct teacher t[2] = {
{40, {"张三", 18}},
{42, {"李四", 28}}
};
int i = 0;
for (i = 0; i < 2; i++) {
printf("老师[%d]的年龄: %d,学生名字:%s, 学生年龄: %d\n", i, t[i].age, t[i].s.name, t[i].s.age);
}
return 0;
}
6. 结构体赋值
// 有警告
#define _CRT_SECURE_NO_WARNINGS
# include<stdio.h>
#include <string.h>
#include <stdlib.h>
struct stu {
char name[20];
int age;
};
int main() {
struct stu s;
strcpy(s.name, "rose");
s.age = 18;
printf("名字是:%s, 年龄: %d\n", s.name, s.age);
// 结构体赋值
struct stu s2 = s;
// 和拷贝一样memcpy(&s2, &s1, sizeof(s1))
printf("名字是:%s, 年龄: %d\n", s2.name, s2.age);
// 这是两个变量,可以输出地址查看
printf("s的地址: %d, s2的地址: %d", &s, &s2);
return 0;
}
7. 结构体和指针
- 普通结构体指针
- 指向堆区空间的结构体指针
- 结构体中套指针
#define _CRT_SECURE_NO_WARNINGS
# include<stdio.h>
#include <string.h>
#include <stdlib.h>
struct stu {
char name[20];
int age;
};
struct stu2 {
char* name;
int age;
};
int main() {
// 1. 普通结构体指针
struct stu s = { "milk", 23 };
struct stu* p = &s;
printf("1. \n");
printf("名字是:%s, 年龄: %d\n", p->name, p->age);
printf("名字是:%s, 年龄: %d\n", (*p).name, (*p).age);
// 2. 指向堆区空间的结构体指针
struct stu* p2 = (struct stu *)malloc(sizeof(struct stu));
strcpy(p2->name, "rose9");
p2->age = 27;
printf("2. \n");
printf("名字是:%s, 年龄: %d\n", p2->name, p2->age);
printf("名字是:%s, 年龄: %d\n", (*p2).name, (*p2).age);
// 3. 结构体中套指针
struct stu2* p3 = (struct stu2*)malloc(sizeof(struct stu2));
p3->name = (char*)malloc(strlen("jack") + 1);
strcpy(p3->name, "rose");
p3->age = 29;
printf("3. \n");
printf("名字是:%s, 年龄: %d\n", p3->name, p3->age);
printf("名字是:%s, 年龄: %d\n", (*p3).name, (*p3).age);
if (p3->name != NULL) {
free(p3->name);
p3->name = NULL;
}
if (p3 != NULL) {
free(p3);
p3 = NULL;
}
return 0;
}
8. 结构体作为函数参数
- 作为普通变量做函数参数
- 指针变量做函数参数
#define _CRT_SECURE_NO_WARNINGS
# include<stdio.h>
#include <string.h>
#include <stdlib.h>
void foo(struct stu tmp) {
printf("名字是:%s, 年龄: %d\n", tmp.name, tmp.age);
strcpy(tmp.name, "milk");
printf("名字是:%s, 年龄: %d\n", tmp.name, tmp.age);
}
void foo2(struct stu* tmp) {
printf("名字是:%s, 年龄: %d\n", tmp->name, tmp->age);
strcpy(tmp->name, "rose");
tmp->age = 27;
printf("名字是:%s, 年龄: %d\n", tmp->name, tmp->age);
}
int main() {
struct stu s = { "lily", 20 };
foo(s);
printf("名字是:%s, 年龄: %d\n", s.name, s.age);
foo2(&s);
printf("名字是:%s, 年龄: %d\n", s.name, s.age);
return 0;
}
输出结果:
名字是:lily, 年龄: 20
名字是:milk, 年龄: 20
名字是:lily, 年龄: 20
名字是:lily, 年龄: 20
名字是:rose, 年龄: 27
名字是:rose, 年龄: 27
9. 共用体(联合体)
联合union是一个能在同一个存储空间存储不同类型数据的类型
联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体
# include<stdio.h>
#include <string.h>
#include <stdlib.h>
struct stu {
char name[20];
int age;
};
union test {
unsigned char a;
unsigned int b;
unsigned short c;
};
int main() {
union test tmp;
// 1. 共用体中元素地址是一样的
printf("&(tmp.a) = %p, &(tmp.b) = %p, &(tmp.c) = %p\n", &(tmp.a), &(tmp.b), &(tmp.c));
//2. 共用体变量大小是最大元素大小
pritf("sizeof(tmp) = %d\n", sizeof(tmp));
// 3. 给其中一个赋值,会影响其他元素
tmp.b = 0x44332211;
printf("tmp.a = %x, tmp.b = %x, tmp.c = %x\n", tmp.a, tmp.b, tmp.c);
tmp.a = 0x00;
printf("tmp.a = %x, tmp.b = %x, tmp.c = %x\n", tmp.a, tmp.b, tmp.c);
return 0;
}
输出结果:
&(tmp.a) = 000000378D8FF574, &(tmp.b) = 000000378D8FF574, &(tmp.c) = 000000378D8FF574
sizeof(tmp) = 4
tmp.a = 11, tmp.b = 44332211, tmp.c = 2211
tmp.a = 0, tmp.b = 44332200, tmp.c = 2200
10. typedef就是取别名
#define _CRT_SECURE_NO_WARNINGS
# include<stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRUE 1
typedef struct test {
int a;
char b;
short c;
}TEST, *PTEST;
int main() {
printf("TRUE = %d\n", TRUE);
TEST t1;
t1.a = 10;
t1.b = 'b';
t1.c = 40;
PTEST p = &t1;
printf("p->a = %d, p->b = %c, p->c = %d\n", p->a, p->b, p->c);
return 0;
}
输出结果:
TRUE = 1
p->a = 10, p->b = b, p->c = 40
typedef struct test {
int a;
char b;
short c;
}*PTEST;
//相当于
typedef struct test {
int a;
char b;
short c;
}* PTEST;
//给struct test {
// int a;
// char b;
// short c;
//}*起名为PTEST
总结
结构体在 C 语言中非常有用,它可以帮助你更有效地组织和管理复杂的数据结构,适用于很多实际的编程场景,如数据库编程、图形编程等领域。
这部分很基础,也很有意思,后面的话,我考虑使用结构体进行一些操作,发一些博客。
这边博客仅仅是基础的使用,后面会尽量细一些,丰富一些。