C语言中的结构体

把一些基本类型数据组合在一起,形成一个新的复合数据类型,这个新的类型就叫结构体。比如一个学生信息,就包含学号、名字和年龄等。

定义结构体的三种方式:

  1. 定义一个结构体类型(以学生信息为例),并定义一个结构体变量:

    struct Student
    {
        int num;
        char name[32];
        double score;
    };
    int main(void)
    {
        struct Student stu1 = {1,"Andy",99};
        return 0;
    }
    

    语句struct Student stu1={1,"Andy",99};定义了一个名为stu1的结构体变量,这个变量的类型是struct Student

    这样子定义变量可以直接整体初始化(要按照顺序):={1,"Andy",99},也可以用点运算符来初始化:stu1.num=1; ……。如果定义完变量后没整体初始化,则只能用点运算符进行单个的赋值。

  2. 也可以在定义结构体类型的时候就紧接着定义出几个结构体变量(一般不推荐这么定义):

    struct Student
    {
        int num;
        char name[32];
        double score;
    }stu1,stu2;
    int main(void)
    {
        stu1.num = 1;
        stu1.name = "Andy";
        stu1.score = 99;
        return 0;
    }
    

    不推荐的原因是:如果再想使用【定义的这个结构体类型】来另外定义一个新变量,会出问题。

  3. 如果像第二种方式,定义结构体类型后紧接着定义了一个变量,则还可以忽略结构体的名称(一般也不推荐这么定义):

    struct
    {
        int num;
        char name[32];
        double score;
    }stu1;
    int main(void)
    {
        stu1.num = 1;
        stu1.name = "Andy";
        stu1.score = 99;
        return 0;
    }
    

取出结构体变量中的元素来使用的两种方式:

  1. 使用.

    struct Student
    {
        int num;
        char name[32];
        double score;
    };
    int main(void)
    {
        struct Student stu1 = {1,"Andy",99};
        stu1.num = 1;
        printf("%d\n",stu1.num);
        return 0;
    }
    
  2. 使用->(指针用):

    struct Student
    {
        int num;
        char name[32];
    };
    int main(void)
    {
    	struct Student st1 = {1,"Jason"};
    	struct Student * p = &st1;
    	printf("%s\n",p->name);
        return 0;
    }
    
    • 上面代码中,指针p的类型是struct Student *
    • 语句struct Student * p = &st1;记得要加上&,不能去掉
    • p->name在计算机内部会被转化成(*p).name,两者是等价的
    • p->name的含义是:p所指向的结构体变量中的name这个成员
    • 每个成员都是在结构体中的一个域,也称为域表(或成员列表)

结构体的一些性质

  1. 结构体指针与sizeof

    struct Student
    {
        int num;
        char name[32];
    };
    int main(void)
    {
    	struct Student st1 = {1,"Jason"};
    	struct Student *p = &st1;
    	printf("%d\n",sizeof(p));//输出结果:8
        printf("%d\n",sizeof(*p));//输出结果:36
        return 0;
    }
    

    sizeof(p)的值为8是因为:指针变量不管是什么类型,本身所占的大小都是一样的,在64位计算机中,指针变量都是占8个字节

    sizeof(*p)的值是36是因为int num是整型数,占4个字节,char name[32]占32个字节

  2. 结构体变量作为函数参数

    struct Student
    {
        int num;
        char name[32];
    };
    void func1(struct Student stu)
    {
        stu.num = 2;
    }
    void func2(struct Student * p)
    {
        p->num = 2;
    }
    int main(void)
    {
    	struct Student st1 = {1,"Jason"};
    	func1(st1);
        printf("%d\n",st1.num);//输出结果:1
       	func2(&st1);
        printf("%d\n",st1.num);//输出结果:2
        return 0;
    }
    

    func1函数并不能改变st1里面的成员的数值,而func2函数可以,因为st1的地址作为参数传进了func2

    复习一个知识点:指针的优点有:传递速度更快,耗用内存小,执行速度快

    以上面代码为例,在调用func1时,系统需要先在内存空间里划分sizeof(struct Student)这么大的空间,然后再把st1的数据拷贝过来。如果struct Student占用内存很大,那就要耗费很多空间,程序执行速度也会受影响

    而在调用func2时,系统不需要再另外划分空间,只需把st1的地址传过去就行了,相比之下,数据传递就快很多,内存空间也耗用更少,程序执行速度更快

  3. 定义一个结构体数组:

    struct Student
    {
        int num;
        char name[38];
        double score;
    };
    
    int main(void)
    {
        struct Student arr[3] = {{1,"Anna",99},{2,"Ann",100},{3,"Jane",99}};
        printf("%d",arr[i].num);//输出结果:1
        return 0;
    }
    
  4. 结构体与动态内存分配:

    struct Student
    {
        int num;
        char name[32];
    };
    int main(void)
    {
        struct Student *p;
        int num = 5;
        //p = (struct Student)malloc(num*sizeof(struct Student));//error
        //p = (struct Student *)malloc(num*sizeof(struct Student));//OK
        p = malloc(num*sizeof(struct Student));//OK
        return 0;
    }
    

    在上面的代码中,使用malloc()时如果前面加强制转换struct Student会报错:conversion to non-scalar type requested,因为malloc()返回的是指针类型(标量),不能强制转换为结构体类型(非标量)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值