c语言结构体知识点

1.为什么要使用结构体

在c语言中有很多基础数据类型,在储存学生信息时需要用到多种基础数据类型比如成绩学号姓名,并且调用起来很麻烦,所以在c语言中专门有一种类型叫做结构体可以用来储存学生信息。

2.如何声明结构体

1.struct关键字

struct是一个关键字如果想使用结构体就要用struct声明具体形式如下

struct Student//结构体名称{
 char *name;
 int id;
 int age;
 
};

2.结构体成员

结构体成员包括结构体类型(结构体名称),结构体成员,结构体变量

struct Student//结构体名称{
 char *name;//成员
 int id;//成员
 int age;//成员
 
}stu1;//结构体变量

 3.空结构体(了解)

空结构体指的是没有成员的结构体

struct student//结构体类型{

 //TODO
 
}stu1;//结构体变量

 4.匿名结构体(了解)

顾名思义匿名结构体就是没有名称的结构体

struct //结构体类型{
 char *name;//成员
 int id;//成员
 int age;//成员
 
}stu1;//结构体变量

 5.使用typedef

typedef是起到了便利结构体调用的作用,它可以重新命名结构体类型(结构体名称),为了区分typedef重新定义的结构体名称和变量名,最要在把结构体名称的首字母大写

声明一个变量的基本结构是:基本数据类型+变量名

在main函数中声明一个结构体变量应该为:

#include <studio.h>


struct Student{
  char *name;
  int id;
  int age;
};

int main(){

  struct Student stu1;
  struct Student stu2;
  ...

  return 0;
}

但是我们利用typedef可以这样:

#include <studio.h>


struct Student{
  char *name;
  int id;
  int age;
};

int main(){

  typedef struct Student Student;
  Student stu1;
  Student stu2;
  ...

  return 0;
}

或者我们可以在声明结构体(这是这个结构体可以是匿名结构体)时就可以用typeof,具体如下 :
 

#include <studio.h>


/*typedef struct {
  char *name;
  int id;
  int age;
}Student;
 */ //or//

typedef struct Student{
  char *name;
  int id;
  int age;
}Student;

int main(){

  
  Student stu1;
  Student stu2;
  ...

  return 0;
}

 6.嵌套结构体

比如我想在Student结构体里插入一个结构体Birthday,Birthday为一个结构体他的数据有年月日,

#include <studio.h>


typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;//新的结构体类型(名称)

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday(类型) birthday(变量);
}Student;

int main(){

  
  Student stu1;
  Student stu2;
  ...

  return 0;
}

当然在生日这个结构体里也可以嵌套其他的结构体 

3.结构体变量

1.声明结构体变量

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;//新的结构体类型(名称)

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday(类型) birthday(变量);
}Student;

这两个部分是声明结构体,如果不使用的话不会占用内存,需要用结构体类型来声明变量才能分配内存空间(深红色部分就是结构体类型)

有两种声明变量的方式,一是如下图这个在main函数中定义

#include <studio.h>

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;//新的结构体类型(名称)

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday(类型) birthday(变量);
}Student;

int main(){

  
  Student stu1,stu2;
 
  ...

  return 0;
}

二是直接在声名结构体时定义

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;//新的结构体类型(名称)

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday(类型) birthday(变量);
}Student, stu1,stu2;

2.给结构体变量赋值 

1.简单结构体赋值

给结构体赋值时只能挨个赋值比如我要给下边这个结构体赋值

 typedef struct Student{
  char *name;//姓名
  int id;//学号
  int age;//年龄

  int score;//成绩
 
}Student, stu1;

我可以在main函数中这样写 

int main()
{
  stu1 = {"xiaoming",101,18,98};
}

2.嵌套结构体赋值

如果我现在要给下列的嵌套结构体赋值应该怎么改呢

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;//新的结构体类型(名称)

 typdef struct Student{
  char *name;
  int id;
  int age;
  Birthday(类型) birthday(变量);
}Student, stu1;

 只要在括号里对应位置多加一个大括号供给结构体变量birthday赋值即可具体形式如下

int main()
{
  stu1 = {"xiaoming",101,18,{2006,1,18}}
  
}

3.访问结构体变量

访问结构体变量需要“.”操作符且结构体的数据只能单个访问

(变量名).(数据)如 stu1.*name              stu1.id

如果要访问上边的birthday的数据要连续使用"."操作符比如我要访问上边birthday的年月日,

//打印birthday年月日
#include <studio.h>

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday
}Student stu1;

int main()
{

  stu1 = {"xiaoming",101,18,{2006,1,18}}
  printf("%d-%d-%d",stu1.birthday.year,stu1.birthday.mouth,stu1.birthday.day);

  return 0;
}

4.结构体作为函数参数的使用

此时我想创造一个函数用来将结构体的数据打印出来

#include <studio.h>
void print(Student stu1)
{
  printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",stu1.*name,stu1.id,stu.age,stu1.birthday.year,stu1.birthday.mouth,stu1.birthday.day);
    
}


typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday
}Student ;

int main()
{

 Student stu1 = {"xiaoming",101,18,{2006,1,18}};
  stu2 = {"xiaohua",102,19,{2005,1,20}};
  print(stu1);
  print(stu2);

  return 0;
}

4.结构体指针

 1. 了解结构体指针的优点

    运用指针前  我们要先了解为什么要运用指针,指针有什么优点值得我们用?

   在结构体给函数传参时,这个过程要完成数据的拷贝,就比如上边的打印结构体的函数,如果利用指针,我们都知道指针利用的是地址,我在只需要在主函数中将stu1与stu2的地址传给函数。函数接收到两个的地址而不是数据的拷贝,大大加快了运行效率

2.声明结构体指针

声明结构体指针方式:

声明一个指向结构体变量的指针,假设刚好有一个stu1

Student *pStu = &stu1;//指针名可以随意取

 传参过程的书写形式,注意如何传参(特别是函数内访问结构体成员的变化

3.指针访问结构体成员(单个结构体与嵌套结构体)

#include <studio.h>


 typedef struct Student{
  char *name;
  int id;
  int age;
}Student ;
void print(Student *pStu)
{
  printf("姓名:%s 学号:%d 年龄:%d ",pStu->name,pStu1->id,pStu->age);
    
}//注意!!!!!如果要利用结构体指针则访问变量时要变换"."语句为"->"语句

int main()
{

 Student stu1 = {"xiaoming",101,18};

 Student *pStu = stu1;

  print(pStu);


  return 0;
}

指针访问单个结构体成员 

void print(Student *pStu)
{
  printf("姓名:%s 学号:%d 年龄:%d ",pStu->name,pStu1->id,pStu->age);
    
}//注意!!!!!如果要利用结构体指针则访问变量时要变换"."语句为"->"语句
 

注意@!!!!!! 我们可以观察到结构体成员的访问不再是(结构体变量名称).(结构体成员)的形式而是变成了(指针名称) -> (结构体成员)的形式

而且声明结构体指针的方式与声明整形字符型的指针形式一致,都是(数据类型)+(*指针名称)

函数接收参数时注意括号内要接收完整 数据类型+名称(*指针名称)或其他

关于利用指针传参时调用嵌套结构体数据的不同之处

指针访问嵌套结构体成员(!!!!!重点!!!!!)

#include <stdio.h>


typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday birthday;
}Student ;
void print(Student *pStu)
{
  printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",pStu->name,pStu->id,pStu->age,pStu->birthday.year,pStu->birthday.mouth,pStu->birthday.day);
    
}
int main()
{

 Student stu1 = {"xiaoming",101,18,{2006,1,18}};
 Student stu2 = {"xiaohua",102,19,{2005,1,20}};
 Student *pStu = &stu1;//指针指向stu1
 print(pStu);
 pStu = &stu2;//指针重新指向stu2
 print(pStu);

  return 0;
}

 void print(Student *pStu)
{
  printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",pStu->name,pStu->id,pStu->age,pStu->birthday.year,pStu->birthday.mouth,pStu->birthday.day);
    
}

birthday与year mouth day之间并没有引用指针所以不会改变它们之间的调用方式

番外篇->结构体指针函数传参的实现方式,上面提到了在main函数中定义一个指针来指向结构体变量stu1,下边直接传地址的方式更加简单便捷,注意!!!只有单个结构体变量可以这样

typedef struct
{
  char name[10];
  int id;
}stu;


int main()
{
  stu stu1;
  chuancan(&stu1);
}
void chuancan(stu *p)
{
}

5.结构体占用的内存

内存对齐问题

typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday,birthday;
printf("%d",sizeof(birthday));

运行结果为12(int 所占字节数为4)

typedef struct Birthdy{
  int year;
  char mouth;
   
}Birthday,birthday;
printf("%d",sizeof(birthday));

运行结果为8(内存对齐)

typedef struct Birthdy{
  int year;
  char mouth;
  char a[3];
}Birthday,birthday;
printf("%d",sizeof(birthday));

运行结果为8  char类型总占字节数与int类型相同不触发内存补齐

6.结构体数组 

如果此时要储存多个学生的姓名成绩学号等数据,一一输入太麻烦,这时候就用到结构体数组

#include <stdio.h>


typedef struct Birthdy{
  int year;
  int mouth;
  int day;
}Birthday;

 typedef struct Student{
  char *name;
  int id;
  int age;
  Birthday birthday;
}Student ;


int main()
{

 
 Student Students[]=//结构体数组名称
{
  {"xiaoming",101,18,{2006,1,18}},
  {"xiaohua",102,19,{2005,1,20}},
  {"xiaohua",102,19,{2005,1,20}},
  {"xiaohua",102,19,{2005,1,20}}
  ....
};

  return 0;
}

最后的知识点设计了指针,数组,函数,结构体的混合知识较为复杂需要多看几遍进行理解 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值