结构体

本文深入探讨C语言中结构体的使用,包括typedefstruct与struct的区别,结构体成员的初始化,同类型结构体间的赋值,结构体的值传递与地址传递,以及结构体内存对齐原理。通过实例解析,帮助读者理解结构体在C编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.typedef struct 与 struct

C编译器中

 

  • typedef struct
 typedef struct student
 {
     int ID;
     char name[20];
     char sex;
     int age;
 }Stu;

这样定义结构体,可以这样初始化

     Stu s1={1,"xiaoming",'m',18};

 

  • struct
struct student
 {
     int ID;
     char name[20];
     char sex;
     int age;
 };

初始化如下

     struct student s1={1,"xiaoming",'m',18};

 

二.同类型结构体赋值

 typedef struct student
 {
     int ID;
     char name[20];
     char sex;
     int age;
 }Stu;

int main()
{
     Stu s1={1,"xiaoming",'m',18};
     Stu s2=s1;
}

 

 

若只给结构体中某几个变量赋值

 typedef struct student
 {
     int ID;
     char name[20];
     char sex;
     int age;
 }Stu;

int main()
{
     Stu s1={.name="xiaoming",.age=18};
     Stu s2=s1;
}

未初始化的char型与char型数组输出为空,未初始化的int型输出为0

 

三.结构体按值传递,按地址传递

 

1.访问元素

  • 访问结构体普通变量中各项值时,用“.”


 void my_printf(Stu s)
 {
     printf("%d,%s,%c,%d\n",s.ID,s.name,s.sex,s.age);
 }
  •  访问结构体中指针变量,用“->”
 void my2_printf(Stu *s)
 {
    (*s).ID=5;
    printf("%d,%s,%c,%d\n",s->ID,s->name,s->sex,s->age);
 }

 

2.按值传递,按地址传递

#include <stdio.h>

typedef struct birthday
{
    int year;
    int month;
    int day;
}Bir;

typedef struct student
{
    int ID;
    char name[20];
    char sex;
    int age;
    struct birthday mbirthday;
    struct student *p;
}Stu;

void my_printf(Stu s)
{
    printf("%d,%s,%c,%d,%d-%d-%d\n",s.ID,s.name,s.sex,s.age,(s.mbirthday).year,(s.mbirthday).month,(s.mbirthday).day);
    s.ID=4;
}


void my0_printf(Stu s)
{
    printf("%d,%s,%c,%d,%d-%d-%d\n",s.ID,s.name,s.sex,s.age,(s.mbirthday).year,(s.mbirthday).month,(s.mbirthday).day);
    
}

void my2_printf(Stu *s)
{
   printf("%d,%s,%c,%d,%d-%d-%d\n",s->ID,s->name,s->sex,s->age,(s->mbirthday).year,(s->mbirthday).month,(s->mbirthday).day); 
   s->ID=5;
}

void my20_printf(Stu *s)
{
   printf("%d,%s,%c,%d,%d-%d-%d\n",s->ID,s->name,s->sex,s->age,(s->mbirthday).year,(s->mbirthday).month,(s->mbirthday).day); 
}

int main()
{
    Stu s1={1,"xiaoming",'m',18,{2000,1,1}};


    my_printf(s1);
    my0_printf(s1);


    my2_printf(&s1);
    my20_printf(&s1);
    
    my_printf(s1);
    my2_printf(&s1);
    return 0;

}

 

 

 

 

 

  •  设计了4个输出函数,my_printf是按值传递的函数,先输出初始化后的s1,输出后将ID改为5
  • my0_printf是再次输出s1,由于前两个输出函数是按值传递,只是副本中的ID被修改,并不是真正的s1中ID被修改,且my_printf执行完后立即释放,副本也被释放,真正的ID仍为 1,所以再次输出s1,ID仍为5(此时输出的4也为副本中的4)
  • my2_printf是按地址传递的函数,此函数也是先输出s1,再将ID改为5
  • my20_printf验证了按地址传递是否修改的是真正的s1中ID,实验结果表明,修改ID是修改真正s1中的ID,并不是副本
  • 再次调用按值传递的my_printf与按地址传递的my2_printf,实验结果可以证明真正的s1的ID被改为5

 

内存示意图

 

按值传递

 

按地址传递

 

 

四.结构体内存空洞 

1. 结构体内存空洞:指的是为提高效率,系统在内存中使数据存储空间“对齐”的现象

 

#include <stdio.h>
struct s1
{
    int a;
    char b;
    int c;
};
int main()
{
    struct s1 s;
    printf("%d\n",sizeof(s));
    return 0;
}

 

 

 

此结构体中变量类型是int,char,int,按理说应该大小为9,但由于结构体内存空洞,给int分配4个字节的空间,char类型数据只需一个字节空间,但为了对齐,也分配4个字节,只占用1个字节,剩余3个字节空闲,最后的int类型分配4个字节空间,3*4=12,整个结构体占用12个字节空间

 

 2.

#include <stdio.h>
struct s1
{
    char a;
    char b;
    int c;
};
int main()
{
    struct s1 s;
    printf("%d\n",sizeof(s));
    return 0;
}

 

 

 

在这个结构体中,变量类型为char,char,int,最开始给char分配了一个字节空间,之后的char类型的一个字节空间紧随之前的char,为与int型变量对齐,两个char型变量共占用4个字节空间,其中2个字节使用,2个字节空闲,2*4=8,整个结构体占用8个字节空间

 

 3.

#include <stdio.h>
struct s1
{
    char a;
    char b;
    char c;
};
int main()
{
    struct s1 s;
    printf("%d\n",sizeof(s));
    return 0;
}

 

 

 

由于此结构体有3个char型变量,每个char型变量分配1个字节空间,3*1=3,此结构体共占用3个字节空间

 

4.

#include <stdio.h>
struct s1
{
    short a;
    char b;
    short c;
};
int main()
{
    struct s1 s;
    printf("%d\n",sizeof(s));
    return 0;
}

 

 

 

short类型变量占用2个字节,char型变量为对齐,也被分配2个字节,使用一个,空闲一个,最后的short型占用两个字节,2*3=6,整个结构体占用6个字节空间

 

5. 

#include <stdio.h>
struct s1
{
    double a;
    char b;
    short c;
};
int main()
{
    struct s1 s;
    printf("%d\n",sizeof(s));
    return 0;
}

 

 

 

double型变量占用8个字节空间,由于32位系统,内存以4个字节为1个单位存放数据,8=4+4,short型与char型共占用4个字节空间,3个字节使用,1个字节空闲,4*3=12,整个结构体占用6个字节空间。

 

6.总结

  •  32位系统,内存以4个字节为1个单位存放数据

  • 4个字节为一组成为字对齐,2个字节为一组是半字对齐

  • short与int、int与char、double与任何数据类型均是字对齐

  • 单独只有short与char是半字对齐

  • 定义结构体变量时,要注意书写的变量顺序,避免大量内存浪费,影响效率

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值