C语言基础-结构体和其他数据结构
补充知识点:条件编译
- 根据宏是否定义
#ifdef <macro> // ... #else // ... #endif // Demo: #define _DEBUG_ int main(int argc, const char *argv[]) { #ifdef _DEBUG_ printf("DEBUG"); #else printf("NO DEBUG"); #endif }
- 根据宏的值
#if <macro>条件语句 // ... #else // ... #endif // Demo: #define _DEBUG_ 1 int main(int argc, const char *argv[]) { #if _DEBUG_ == 2 printf("DEBUG"); #else printf("NO DEBUG"); #endif }
初识结构体
- 在实际处理对象中,有许多信息是由多个不同类型的数据组合在一起进行描述,而且这些不同类型的数据是互相联系组成了一个有机的整体。此时,就要用到一种新的构造类型数据--结构体(structure),简称结构。
- 结构体的使用为处理复杂的数据结构(如动态数据结构等)提供了有效的手段,而且,它们为函数间传递不同类型的数据提供了方便。
定义:
struct 结构体名 { 数据类型 成员1; 数据类型 成员2; ... 数据类型 成员n; };
- 在大括号中的内容称为"成员列表"或"域表",其中,每个成员名的命名规则与变量名相同
- 数据类型可以是基本变量类型和数组类型,或是一个结构体类型
- 用`;`作为结束符。整个结构体的定义也用分号作为结束符
// Demo int main(int argc, const char *argv[]) { // Worker struct worker{ long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; }; int age = 10; // age是变量名 }
- 说明
结构体类型中的成员名可以与程序中的变量名相同,二者并不代表同一个对象,编译程序可以自动对它们进行区分
- 结构体的特点
- 结构体类型是用户自行构造的
- 它由若干个不同的基本数据类型的数据构成
- 它属于c语言的一种数据类型,与整形、实型相等。因此,它定义时不分配空间,只有定义变量才分配空间
结构体变量声明:
struct 结构体名 变量名; // Demo1 普通定义: int main(int argc, const char *argv[]) { // Worker结构体定义 struct worker { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; }; struct worker nowWorker1,nnwWorker2; // 定义结构体变量 } // Demo2 在构造结构体时定义 int main(int argc, const char *argv[]) { // Worker结构体定义 struct worker { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; } nowWorker1,nowWorker2; // 定义结构体变量 nowWorker } // Demo3 匿名结构体 int main(int argc, const char *argv[]) { // 匿名结构体 struct { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; } nowWorker; // 定义结构体变量 nowWorker }
获取结构体大小
sizeof(结构体名) // 求出给定结构体占用内存空间的字节数 // Demo: sizeof(struct worker) // 直接求结构体 sizeof(nowWorker1) // 求结构体变量
结构体变量的使用
结构体变量.成员名
int main(int argc, const char *argv[]) { // Worker结构体定义 struct worker { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; } nowWorker; // 定义结构体变量 nowWorker // 赋值 nowWorker.number = 1; *nowWorker.name = *"test"; nowWorker.sex = 1; nowWorker.age = 20; nowWorker.salary = (float)10000.1; strcpy(nowWorker.address,"address"); // 使用这种间接拷贝也行 printf("number :%ld\n", nowWorker.number); printf("name %s\n", nowWorker.name); printf("sex %d\n", nowWorker.sex); printf("age: %d\n", nowWorker.age); printf("salary: %f\n", nowWorker.salary); printf("address: %s\n", nowWorker.address); } int main(int argc, const char *argv[]) { // Worker结构体定义 struct worker { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; } nowWorker; // 定义结构体变量 nowWorker // 赋值 nowWorker.number = 1; *nowWorker.name = *"test"; nowWorker.sex = 1; nowWorker.age = 20; nowWorker.salary = (float)10000.1; strcpy(nowWorker.address,"address"); // 使用这种间接拷贝也行 printf("number :%ld\n", nowWorker.number); printf("name %s\n", nowWorker.name); printf("sex %d\n", nowWorker.sex); printf("age: %d\n", nowWorker.age); printf("salary: %f\n", nowWorker.salary); printf("address: %s\n", nowWorker.address); }
- 注意:不能将结构体变量作为一个整体加以引用,只能对结构体类型变量中的各个成员分别引用
结构体变量的初始化
struct 结构体名 { }变量名={初始化数据表} struct 结构体名 变量名={初始数据表}
// Demo1: int main(int argc, const char *argv[]) { // Worker结构体定义 struct worker { long number; char name[20]; char sex; int age; // age是成员名 与外部变量不冲突 float salary; char address[80]; }; struct worker nowWorker = { 20, "小明", 1, 20, 1000.1, "address" }; // 初始化结构体变量 printf("number :%ld\n", nowWorker.number); printf("name %s\n", nowWorker.name); printf("sex %d\n", nowWorker.sex); printf("age: %d\n", nowWorker.age); printf("salary: %f\n", nowWorker.salary); printf("address: %s\n", nowWorker.address); }
嵌套结构体的使用
结构体变量.嵌套结构体成员名.成员
int main(int argc, const char *argv[]) { // address struct address { char address[20]; }; // student struct student { char name[20]; int age; float core; struct address address1; }; struct student xiaoming = {"小明",20,60,{"address"}}; printf("%s",xiaoming.address1.address); }
// 匿名结构体的应用 int main(int argc, const char *argv[]) { // student struct student { char name[20]; int age; float core; // 匿名结构体 struct address { char address[20]; } address1; }; struct student xiaoming = {"小明", 20, 60, {"address"}}; printf("%s", xiaoming.address1.address); }
结构体数组
- 具有相同结构体类型的结构体变量也可以组成数组,称它们为结构体数组。结构体数组的每一个数组元素都是结构体类型数据,它们都分布包括各个成员(分量)项
- 定义结构体数组的方法和定义结构体变量的方法相仿,只需说明其为数组即可。可以采用三种方法
int main(int argc, const char *argv[]) { // 匿名 struct { int id; } testList1[3]; // struct struct test { int id; } testList2[5]; // 结构体数组 struct test testList3[10]; }
结构体数组初始化
int main(int argc, const char *argv[]) { struct test { int id; }; // 结构体数组初始化1 struct test testList1[10] = {}; // 结构体数组初始化2 struct test testList2[10] = {{1}, {2}, {3}}; // 结构体数组初始化3 struct test testList3[] = {{1}, {2}, {3}}; }
直接访问 使用 `.成员` 通过指针间接访问 使用 `->成员`
int main(int argc, const char *argv[]) { struct test { int id; }; // 结构体数组初始化1 struct test testList1[10] = {}; // 结构体数组初始化2 struct test testList2[10] = {{1}, {2}, {3}}; // 结构体数组初始化3 struct test testList3[] = {{4}, {5}, {6}}; // 结构体数组访问 // 直接访问 使用 `.` // 通过指针间接访问 使用 `->` printf("%d\n", testList2->id); // 相当于 testList2[0].id printf("%d\n", (*testList2).id); // 相当于 testList2[0].id printf("%d\n", (testList2 + 1)->id); // 相当于 testList2[1].id printf("%d\n", (*(testList2 + 1)).id); // 相当于 testList2[1].id // 修改 testList2->id = 6; // 相当于 testList2[0].id = 6 (*(testList2 + 1)).id = 5; // 相当于 testList2[1].id = 6 printf("%d\n", (*testList2).id); // 相当于 testList2[0].id printf("%d\n", (*(testList2 + 1)).id); // 相当于 testList2[1].id }
结构体指针
struct 结构体名 * 结构体变量
int main(int argc, const char *argv[]) { struct test { int id; }; // 结构体指针的声明 struct test *test1; test1 = &(struct test) { 1 }; // 通过指针间接访问 使用 `->成员` printf("%d", test1->id); // 直接访问 使用 `.成员` printf("%d", (*test1).id); }
初始共用体(联合)
共用体概念:
在C语言中,不同数据类型的数据可以使用共同的存储区域,这种数据构造类型称为共用体,简称共用,又称联合体。共用体在定义、说明和使用形式上与结构体类似。两者本质上的不同仅在与内存的方式上
共用体的声明
union 共用体名
{
成员列表;
};
union demo { int i; char c; float f; };
- 这里定义了一个共用类型 union test,它由三个成员组成,这三个成员在内存中使用了共同的存储空间。
- 由于共同体中各成员的数据长度往往不同,所以共用体在存储时总是按成员中数据长度最大的成员占用内存空间 如果将union换成struct则结构体变量的长度应为(2+1+4=7)而union的共用体变量长度应为(4)
声明共用体变量
与结构体类似
共用体变量的赋值
在使用共用体变量的数据时要注意:在共用体类型变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用
int main(int argc, const char *argv[]) { union demo { int i; char c; float f; }; union demo demo1; demo1.i = 1; demo1.f = 1.5; // 此时demo1.i已经被覆盖 demo1.c = 'a'; // 此时demo1.f已经被覆盖 printf("%d", demo1.c); }
初始typedef
在c语言中,允许使用typedef定义新的数据类型
typedef <已有数据类型> <新数据类型> // Demo typedef int MYINT; MYINT i ; <==> int i;
typedef常用与结构体变量的简化
struct test { int id; }; typedef struct test mytest; mytest i; // 等于 struct test i;
Songzhibin