C语言 || 结构体初阶

目录

结构体类型的声明

结构的的基础知识

结构体的声明

结构成员的类型

 结构体的初始化

结构体成员的访问

两个操作符(.)和(->)

(.)操作符

(->) 操作符

结构体传参 

传值调用

传址调用(传地址)

 问:print1和print2哪一个更好?

问:什么是函数调用的参数压栈 


结构体类型的声明

结构的的基础知识

结构是一些值的结合,这些值称为成员变量。结构的每个成员可以是不同类型的变量

结构体的声明

以定义一名学生类型为例

struct Stu //学生类型
{
    //成员变量
    char name[20]; //名字
    int age; //年龄
    char id[20]; //学号
}s1,s2; //s1和s2是结构体变量
//s1和s2是全局变量
int main()
{
    struct Stu s;//创建了一个对象s,s是局部变量
    return 0; 
}

结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其它结构体

struct X
{
    char a;
    short b;
    double c;
};
struct Stu 
{    
    struct X sb; //结构体的成员可以是另一个结构体
    char name[20]; 
    int age; 
    char id[20]; 
};

结构体的成员可以是另一个结构体 


 结构体的初始化

struct X
{
    char a;
    short b;
    double c;
};
struct Stu 
{
    struct X sb; 
    char name[20]; 
    int age; 
    char id[20]; 
};
int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};//结构体的初始化
    return 0;
}

结构体成员的访问

两个操作符(.)和(->)

(.)操作符

结构变量的成员是通过点操作符(.)访问的,点操作符(.)接受两个操作数

struct X
{
    char a;
    short b;
    double c;
};
struct Stu 
{
    struct X sb; 
    char name[20]; 
    int age; 
    char id[20]; 
};
int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    printf("%c,%d,%lf,%s,%d,%s\n", s.sb.a, s.sb.b, s.sb.c, s.name, s.age, s.id);
    return 0;
}

(->) 操作符

另外,在使用结构体指针时,访问结构成员也可以用( -> )操作符 

struct X
{
    char a;
    short b;
    double c;
};
struct Stu 
{
    struct X sb; 
    char name[20]; 
    int age; 
    char id[20]; 
};
int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    struct Stu * ps = &s; //结构体指针
    printf("%c,%d,%lf,%s,%d,%s\n", (*ps).sb.a, (*ps).sb.b, (*ps).sb.c, (*ps).name, (*ps).age, (*ps).id);
    printf("%c,%d,%lf,%s,%d,%s\n", ps->sb.a, ps->sb.b, ps->sb.c, s.name, s.age, s.id);
    return 0;  //用指针访问的两种方法
}

struct Stu * ps = &s;这句代码,“*”代表ps是指针变量,struct Stu代表指针指向的类型是一个结构体类型 


结构体传参 

传值调用


int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    return 0;
}

现在我们想要写一个函数来打印s的内容


int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    print1(s); 
    return 0;
}

在主函数中,将结构体变量s传入print1函数,因此我们也需要一个结构体变量来接收s

​
int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    print2(&s);
    return 0;
}
void print2(struct Stu* m)
{

}

​

传址调用(传地址)

也可以传入s的地址,比如下述代码

int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    print2(&s);
    return 0;
}
void print2(struct Stu* m)
{

}

如果要打印某数

struct X
{
    char a;
    short b;
    double c;
};
struct Stu 
{
    struct X sb; 
    char name[20]; 
    int age; 
    char id[20]; 
};
int main()
{
    struct Stu s = { {'w', 3, 8.14}, "zhangsan", 40, "u2023"};
    print1(s);
    print2(&s);
    return 0;
}
void print1(struct Stu m)
{
    printf("%c\n", m.sb.a); //打印字符‘w’
}
​

void print2(struct Stu* ps)
{
    printf("%c"\n", ps->sb.a); //打印字符‘w’
}

​

 问:print1和print2哪一个更好?

答案:print2更好

原因:

1.print1是传值调用,实参传给形参,需要形参开辟一块与实参大小相同的空间来接收,在空间上有一些浪费,并且传递也需要时间

2.print2是传址调用,指针变量只有4个字节(32位机)或8个字节(64位机),print2的传参效率更高

3.print1中对m操作不会影响原来的s,print2可以改变s

4.函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,会导致性能的下降

结论:结构体传参的时候,要传结构体的地址

问:什么是函数调用的参数压栈 

栈是一种数据结构,有着先进的后出,后进的先出的特点

比如我要存储1 2 3 4 5这五个数据

1

2
1

一个一个往下放

5
4
3
2
1

只能从下往上放置数据,这个行为叫做压栈

当要删除某一个元素时,只能从上往下删,这就是先进的后出,后进的先出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值