结构体基本使用
结构体其实跟java
类长得有点像,使用结构体也可以声明变量
1 2 3 4 5 6 7 8
| struct 结构体名 { 数据类型 变量名; ... 数据类型 变量名; };
struct 结构体名 变量名;
|
如下代码声明了一个Person
结构体,并且在main
函数中使用该结构体声明了变量,用结构体声明变量与数组变量有相似之处,即声明结构体变量时如果不赋初始值,编译器会给结构体中的成员分配未初始化值(未初始化的值是不确定的),并分配内存地址,结构体变量的内存地址一旦被分配便不可更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| struct Person{ int age; int height; char* name; char* hobby[]; };
int main() { struct Person person;
person.hobby = {1,2,3};
printf("age = %d\n", person.age);
person.age = 22;
printf("age = %d\n", person.age);
return 0; }
|
用结构体声明变量并对结构体变量所有成员进行初始化,也和数组初始化很像;需要注意的是,结构体中的成员不能包含可变长度的数组,即结构体中的数组必须固定长度;另外注意,指针变量的未初始化值是一个未知的内存地址(也可能是一个特定的内存地址),所以即使包含指针成员的结构体变量不需要初始化,也尽量将指针初始化为NULL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| struct Person{ int age; int height; char* name;
char* hobbies[2]; };
int main() { struct Person person = {25, 180, "John", {"Reading", "Gardening"}};
printf("Age: %d\n", person.age); printf("Height: %d\n", person.height); printf("Name: %s\n", person.name); printf("Hobbies: %s, %s\n", person.hobbies[0], person.hobbies[1]);
return 0; }
|
用结构体声明变量并对结构体变量部分成员进行初始化,未被初始化的部分系统将会为其赋默认值,如整型将会被赋值0
,指针将会被赋值NULL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| struct Person{ int age; int height; char* name;
char* hobbies[2]; };
int main() { struct Person person = {25, 180, "John"};
printf("Age: %d\n", person.age); printf("Height: %d\n", person.height); printf("Name: %s\n", person.name);
printf("Hobbies: %s, %s\n", person.hobbies[0], person.hobbies[1]);
return 0; }
|
也可以对指定的部分成员进行初始化,初始化先后顺序不受结构体中先后顺序的影响,未被初始化的部分系统将会为其赋默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| struct Person{ int age; int height; char* name;
char* hobbies[2]; };
int main() { struct Person person = {.age = 25, .name = "John", .hobbies = {"Reading", "Gardening"}};
printf("Age: %d\n", person.age);
printf("Height: %d\n", person.height); printf("Name: %s\n", person.name); printf("Hobbies: %s, %s\n", person.hobbies[0], person.hobbies[1]);
return 0; }
|
声明结构体的同时可以用结构体声明变量,在之后的使用过程中,再对结构体变量中的成员重新赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct Person{ int age; int height; char* name; char* hobbies[2]; } person1, person2;
int main() { person1.age = 20; person2.age = 30;
return 0; }
|
声明结构体的同时用结构体声明变量,并且对结构体变量赋初始值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| struct Person{ int age; int height; char* name; char* hobbies[2]; }
person1 = {20, 180, "John", {"Reading", "Gardening"}}, person2 = {30, 170, "Jack", {"Reading", "Gardening"}};
int main() { printf("person1 Age: %d\n", person1.age); printf("person1 Height: %d\n", person1.height); printf("person1 Name: %s\n", person1.name); printf("person1 Hobbies: %s, %s\n", person1.hobbies[0], person1.hobbies[1]);
printf("\n");
printf("person2 Age: %d\n", person2.age); printf("person2 Height: %d\n", person2.height); printf("person2 Name: %s\n", person2.name); printf("person2 Hobbies: %s, %s\n", person2.hobbies[0], person2.hobbies[1]);
return 0; }
|
使用typedef
给结构体起别名,用以简化声明结构体变量的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typedef struct Person{ int age; int height; char* name; char* hobbies[2]; } P;
int main() { P person = {20, 180, "John", {"Reading", "Gardening"}};
printf("person Age: %d\n", person.age); printf("person Height: %d\n", person.height); printf("person Name: %s\n", person.name); printf("person Hobbies: %s, %s\n", person.hobbies[0], person.hobbies[1]);
return 0; }
|
没有结构体名的结构体即为匿名结构体,声明匿名结构体时如果不声明结构体变量,那后面就没机会了,因为匿名结构体没有结构体名
1 2 3 4 5 6
| struct { int age; int height; char* name; char* hobbies[2]; } person;
|
当然了除非用typedef
给匿名结构体起别名,感觉这种格式挺好的,使用别名代替结构体名,而且在代码中声明结构体变量时也简洁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typedef struct { int age; int height; char* name; char* hobbies[2]; } P;
int main() { P person = {20, 180, "John", {"Reading", "Gardening"}};
printf("person Age: %d\n", person.age); printf("person Height: %d\n", person.height); printf("person Name: %s\n", person.name); printf("person Hobbies: %s, %s\n", person.hobbies[0], person.hobbies[1]);
return 0; }
|
结构体值传递
结构体变量与数组的不同之处是,数组的传递方式是地址传递,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int main() { int arr[] = { 1,2,3,4,5 };
test(arr);
printf("arr[0] = %d\n", arr[0]);
return 0; }
void test(int arr[]){ arr[0] = 10; }
|
而结构体的传递方式是值传递,即仅把构造体变量的值传入,并不会影响原构造体变量中的数值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int main(){ Person person = { .age = 18, .height = 180, .name = "haha", .hobbies = {"reading"} };
test2(person);
printf("person.age = %d\n", person.age);
return 0; }
void test2(Person person) { person.age = 20; }
|
结构体数组
如下代码,声明了一个Person
结构体,然后使用该结构体声明了一个Person
数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| struct Person { int age; int height; char* name; char* hobbies[2]; };
int main(){ struct Person people[] = { {20, 180, "Jack", {"Sports", "Reading"}}, {22, 170, "John", {"Running"}} };
printf("person Age: %d\n", people[0].age); printf("person Height: %d\n", people[0].height); printf("person Name: %s\n", people[0].name); printf("person Hobbies: %s, %s\n", people[0].hobbies[0], people[0].hobbies[1]);
return 0; }
|
也可以给结构体起别名,用别名声明结构体数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typedef struct Person { int age; int height; char* name; char* hobbies[2]; } Person;
int main() { Person people[] = { {20, 180, "Jack", {"Sports", "Reading"}}, {22, 170, "John", {"Running"}} };
printf("person Age: %d\n", people[0].age); printf("person Height: %d\n", people[0].height); printf("person Name: %s\n", people[0].name); printf("person Hobbies: %s, %s\n", people[0].hobbies[0], people[0].hobbies[1]);
return 0; }
|
声明结构体的同时声明数组,在之后的使用过程中再对结构体数组重新赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| struct Person { int age; int height; char* name; char* hobbies[2]; } people[2];
int main() { people[0].age = 20; people[0].height = 180; people[0].name = "John"; people[0].hobbies[0] = "Reading"; people[0].hobbies[1] = "Sports";
printf("person Age: %d\n", people[0].age); printf("person Height: %d\n", people[0].height); printf("person Name: %s\n", people[0].name); printf("person Hobbies: %s, %s\n", people[0].hobbies[0], people[0].hobbies[1]);
return 0; }
|
声明结构体的同时声明数组,并且对数组进行初始化;其它的一些操作不再列举,都符合结构体变量的声明以及数组的声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| struct Person { int age; int height; char* name; char* hobbies[2]; } people[2] = { {20, 180, "Jack", {"Sports", "Reading"}}, {22, 170, "John", {"Running"}} };
int main(){ printf("person Age: %d\n", people[0].age); printf("person Height: %d\n", people[0].height); printf("person Name: %s\n", people[0].name); printf("person Hobbies: %s, %s\n", people[0].hobbies[0], people[0].hobbies[1]);
return 0; }
|
结构体指针
使用结构体声明结构体指针变量,并取结构体变量的地址值赋值给该指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| struct Person { int age; int height; char* name; char* hobbies[2]; };
int main(){ struct Person person = {20, 180, "Jack", {"Sports", "Reading"}};
struct Person *pointer = &person;
(*pointer).age = 30;
printf("age = %d\n", person.age);
return 0; }
|
结构体的传递方式是值传递,通过结构体指针可以实现地址传递,如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int main(){ Person person = { .age = 18, .height = 180, .name = "haha", .hobbies = {"reading"} };
test2(&person);
printf("person.age = %d\n", person.age);
return 0; }
void test2(Person* pointer) { (*pointer).age = 20; }
|
使用结构体指针调用结构体变量中的成员语法比较麻烦,因此可以使用箭头操作符,如下
1 2 3 4
| (*pointer).age
pointer -> age
|
1 2 3 4 5 6 7 8
| void test2(Person* pointer) { (*pointer).age = 20; }
void test2(Person* pointer) { pointer -> age = 20; }
|
共用体的基本使用
共用体内部可以和结构体一样有多个成员,但是共用体变量同一时间只能有一个赋值成员;共用体的所有成员都在同一个内存地址,所以共用体占用内存的大小就是共用体中占用内存最大的成员的内存大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| union Data{ int int_data1; int int_data2; short short_data; float float_data; };
int main(){
union Data data1 = {.int_data1 = 10}; printf("data = %d\n", data1.int_data1);
union Data data2; data2.short_data = 20; printf("data = %d\n", data2.short_data);
union Data data3 = { .int_data1 = 10,.int_data2 = 30 }; printf("data = %d\n", data3.int_data1);
union Data data4 = { .short_data = 20 }; data4.float_data = 55.5f; printf("data = %d\n", data4.short_data);
return 0; }
|
共用体的变量声明方式即成员调用方式基本和结构体一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| union Data{ int int_data1; int int_data2; short short_data; float float_data; } data2, data3 = {.short_data = 10};
int main(){
union Data data1; data1.float_data = 12.3f;
data2.int_data2 = 6;
data3.short_data = 11;
union Data *pointer = &data1; pointer -> float_data = 23.4f;
return 0; }
|