4 结构体
4.1 结构体操作
- 取地址
#include <stdio.h>
struct Point3D{
int x;
int y;
int z;
};
int main(){
struct Point3D p = {1,2,3};
printf("&p = %p\n",&p);
printf("&(p.x) = %p\n",&p.x);
printf("&(p.y) = %p\n",&p.y);
printf("&(p.z) = %p\n",&p.z);
}
&p = 0x7ffda6be3f64
&(p.x) = 0x7ffda6be3f64
&(p.y) = 0x7ffda6be3f68
&(p.z) = 0x7ffda6be3f6c
结构体名 != 结构体地址;
结构体地址 = 结构体首元素地址。
- 传参
#include <stdio.h>
struct Point3D{
int x;
int y;
int z;
};
void Print(struct Point3D p){
printf("%d %d %d\n",p.x,p.y,p.z);
}
int main(){
struct Point3D p = {1,2,3};
Print(p);
}
整个结构体作为参数传入函数,这时在函数内新建一个结构体并赋值值;
结构体可以作为返回值,也是结构体整体进行复制。
4.2 结构体指针
- 结构体指针访问成员
#include <stdio.h>
struct Point3D{
int x;
int y;
int z;
};
void Print(struct Point3D p){
printf("%d %d %d\n",p.x,p.y,p.z);
}
void PointPtr(struct Point3D* p){
printf("%d %d %d\n",p->x,p->y,p->z);
}
int main(){
struct Point3D p = {1,2,3};
Print(p);
struct Point3D* q = &p;
PointPtr(q);
q->x = 10;
Print(p);
// 三种访问成员方式
printf("%d %d %d\n",p.x,(*q).x,q->x);
}
1 2 3
1 2 3
10 2 3
10 10 10
结论:
1、结构体变量通过.访问成员;
2、结构体指针通过->访问成员;
3、通过修改结构体指针q指向的成员,也会改变结构体变量p成员的值。
4、结构体指针->成员可以看作(*结构体指针).成员
- 结构体指针作为参数
C语言中,通常将结构体指针作为参数传入函数,尤其是当传递的参数类型比地址大的时候,可以使用这种方式既能传递较少的字节数。
4.3 结构数组
结构数组定义方式
#include <stdio.h>
struct Point3D{
int x;
int y;
int z;
};
void Print(struct Point3D p){
printf("%d %d %d\n",p.x,p.y,p.z);
}
int main(){
struct Point3D p[] = {{1,2,3},{4,5,6},{7,8,9}};
for(int i = 0;i < 3;++i){
Print(p[i]);
}
}
1 2 3
4 5 6
7 8 9
打印结构数组;
根据结构数组中y元素大小进行排序;
#include <stdlib.h>
struct Point3D{
int x;
int y;
int z;
};
void Print(struct Point3D p){
printf("%d %d %d\n",p.x,p.y,p.z);
}
void PrintPtr(struct Point3D* p){
printf("%d %d %d\n",p->x,p->y,p->z);
}
int cmp(const void* a,const void* b){
struct Point3D* p = (struct Point3D*)a;
struct Point3D* q = (struct Point3D*)b;
return p->y > q->y?1:-1;
}
typedef void (*Pfunc_t)(struct Point3D); //函数指针
int main(){
struct Point3D p[] = {{1,11,3},{4,5,6},{7,8,9}};
Pfunc_t pfunc;
pfunc = Print;
for(int i = 0;i < 3;++i){
pfunc(p[i]);
}
for(int i = 0;i < 3;++i){
Print(p[i]);
}
//结构体数组排序
qsort(p,3,sizeof(struct Point3D),cmp);
for(int i = 0;i < 3;++i){
PrintPtr(p+i);
}
}
1 11 3
4 5 6
7 8 9
1 11 3
4 5 6
7 8 9
4 5 6
7 8 9
1 11 3
4.4 结构体嵌套
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* name;
int x;
int y;
int z;
} Point;
typedef struct{
Point start;
Point end;
} Line;
void Print(Point p){
printf("%s: %d %d %d\n",p.name,p.x,p.y,p.z);
}
void PrintPtr(Point* p){
printf("%s: %d %d %d\n",p->name,p->x,p->y,p->z);
}
int main(){
Line line = {
{"起点",1,2,3},
{"终点",4,5,6},
};
Line* p = &line;
//打印方式1
printf("%s: %d %d %d\n",line.start.name,line.start.x,line.start.y,line.start.z);
printf("%s: %d %d %d\n",p->end.name,p->end.x,p->end.y,p->end.z);
//打印方式2
Print(line.start);
Print(line.end);
//打印方式3
PrintPtr(&line.start);
PrintPtr(&line.end);
}
结构体嵌套可以看作路径,结构体相当于目录或文件夹,成员相当于文件;
访问文件根据结构体类型选择.
访问或者->
访问。
4.5 联合体
语法:
union 联合体类型名 {
成员
};
联合体和结构体区别:
1、联合体元素公用相同的内存空间,结构体按照内存对齐的方式各自占用不通过的内存空间。
2、联合体的sizeof
是成员中大小的最大值,结构体的sizeof
按照内存对齐的方式计算。
#include <stdio.h>
union Test{
char a;
int b;
double c;
};
struct Test2{
char a;
int b;
double c;
};
union Interger{
int n;
char s[4];
};
int main(){
printf("%d %d\n",sizeof(union Test),sizeof(struct Test2));//结构体大小按照内存对齐的方式计算,联合体大小为成员大小的最大值
union Test t;
printf("%p\n",&t);
printf("%p\n",&t.a);
printf("%p\n",&t.b);
printf("%p\n",&t.c); //所有成员公用相同的内存空间
struct Test2 t2;
printf("%p\n",&t2);
printf("%p\n",&t2.a);
printf("%p\n",&t2.b);
printf("%p\n",&t2.c); //内存对齐 各自占用不同的内存空间
union Interger num;
num.n = 123456;
printf("%x\n",num.n);
for(int i = 0;i < 4;++i){
printf("%hhx\n",num.s[i]);
}
}
8 16
0x7fffe6979850
0x7fffe6979850
0x7fffe6979850
0x7fffe6979850
0x7fffe6979840
0x7fffe6979840
0x7fffe6979844
0x7fffe6979848
1e240
40
e2
1
0