四、C语言初阶:结构体、联合体

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值