目录

1.结构体的定义与使用

2.结构体数组

3.结构体指针

4.结构体然后计算大小

5.typedef关键字

6.结构体常见问题


1.结构体的定义与使用

结构体跟我们之前接触的数组的概念很相似,数组是类型相同的一组变量的集合,而结构体类型不同的一组变量的集合。这样就会使数据更多,类型更丰富,数据量更大。

结构体在定义的时候我们不关心这个结构体里面变量的值,它就类似于模板一样,至于变量的大小或内容我们再编程的时候会给它们补充完整,哪怕定义的变量没有用到也是可以的。

如何定义结构体

在给结构体中的赋值的时候,可以类比我们平时给普通变量赋值的情况。

struct student   //struct关键字+结构体名字
{int score;char name[128];
};    //记得有分号int main()
{     //类型          变量名   初始值int             a   =  10;struct student stu  = {98,"jhsad"}; //struct student可以看作是我们自定义的一种类型return 0;
}

如何访问结构体

上面我们已经定义好了一个结构体,现在我们把结构体里面的值拿出来访问。同样类比普通变量的访问方式。

#include <stdio.h>
#include <string.h> struct student
{int score;char name[128];
};int main()
{   int a = 10;//第一种访问方式struct student stu = {98,"jhsad"};printf("a=%d\n",a);            //普通变量的访问方式printf("score=%d\n",stu.score);//访问结构体用.运算符printf("name=%s\n",stu.name);//第二种访问方式struct student text;text.score = 20;strcpy(text.name,"李四");printf("score=%d\n",text.score);printf("name=%s\n",text.name);return 0;
}

2.结构体数组

结构体数组的定义方式跟上面都一样的,还是通过类比普通数组的定义方式。

#include <stdio.h>struct student
{int sorce;char *name;
};int main()
{
//  类型         变量 大小 int            a  [3];struct student stu[3];return 0;
}

练习:通过结构体数组操作学生成绩

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct student
{int sorce;char *name;
};int main()
{   int i;struct student stu[3];for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++){printf("请输入第%d个学生的名字\n",i+1);stu[i].name = (char *)malloc(128);memset(stu[i].name,'\0',128);scanf("%s",stu[i].name);printf("请输入第%d个学生的成绩\n",i+1);scanf("%d",&stu[i].sorce);}for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++){printf("第%d个学生的名字和成绩\n",i+1);printf("%s:%d\n",stu[i].name,stu[i].sorce); }return 0;
}

3.结构体指针

定义结构体指针的时候要注意两点:

1.如果用结构体指针,就不能用点运算符,访问结构体中的变量要用->

2.指针要注意是否是野指针或者NULL。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct student
{int sorce;char *name;
}; int main()
{   struct student *p;   //定义结构体指针p = (struct student *)malloc(sizeof(struct student)); p->name = (char *)malloc(sizeof(128));  //用->访问结构体中的内容p->sorce = 100;strcpy(p->name,"张三");printf("%s的成绩是%d\n",p->name,p->sorce);free(p);    //释放空间,防止内存泄漏return 0;
}

4.结构体然后计算大小

结构体计算大小由于要遵循计算机的访问规则,所以我们引入了内存对齐和偏移量的概念。

内存对齐简单的可以理解为跟盖章差不多,比如一张纸有12个字节,一个印章有四个字节,那么刚好印章盖三次可以盖完,假设这个印章有5个字节,那么怎么改都不可能刚好盖满12个字节。所以纸的大小一定要和章的大小成整数倍的关系,这样才可以做到对齐。

对齐的方式很浪费空间,但根据计算机的访问规则,大大提高了运行效率。

偏移量可以这样理解,现在我连续定义几个变量,第一个变量成员的大小就是下一个变量成员的偏移量大小。比如第一个成员是一个int型的变量,那么第二个变量成员的偏移量就是四个字节。

因此计算结构体大小的规则:
1.每一个成员的偏移量都必须是该成员的倍数。
2.结构体的大小必须是该结构体字节数最大成员的倍数(数组除外,结构体除外)。

struct s1
{char ch1;  //一个字节char ch2   //一个字节 int ch3;   //四个字节,因此要遵循第一条规则,2个char一共偏移2个字节
};             //不是4的整数倍,因此要再多偏移两个字节,一共偏移8个字节
//可以用sizeof验证一下:printf("%d\n",sizeof(struct student));

再看下面这段代码,我们将解释第二条规则。

下面这段代码如果只遵循第一条规则的话所计算出的大小是9个字节,但是我们还有一个规则结构体的大小必须是该结构体字节数最大成员的倍数。9不是int型大小的整数倍,int型是4个字节,不是9的整数倍。因此我们还需再偏移3个字节,所以改结构体的大小为12个字节。

struct s2
{char ch1;  int ch3;char ch2;
}; 

结构体中包含数组

struct s3
{char ch1;       //1个字节int ch3;        //4+3个字节(多偏移3个字节)char ch2[12];    //12个字节
};                  //共20个字节struct s4
{char ch1;       //1个字节int ch3;        //4+3个字节(多偏移3个字节)char ch2[10];    //10个字节
};                  //多偏移两个字节,共20个字节

结构体中包含结构体

下面的代码不同之处就是一个是声明了结构体且定义了结构体变量,一个是声明了结构体且没有定义了结构体变量,计算出的结果大不相同。

struct s2
{char ch1;       //1个字节int ch2;        //4+3个字节(多偏移3个字节)struct s{char ch3;  int ch4;    //结构体中8个字节}stmp;          //声明结构体且定义了结构体变量float f;        //4个字节
};                  //8+8+4,共20个字节struct s2
{char ch1;       //1个字节int ch2;        //4+3个字节(多偏移3个字节)struct s{char ch3;  int ch4;    //结构体中8个字节};              //声明结构体且没有定义了结构体变量,不占内存空间float f;        //4个字节
};                  //8+4,共12个字节

指定对齐方式(向4对齐)

#pragma pack(4) //指定向4对齐   最大是8
struct s5
{char ch1;  //1个字节int ch3;   //4+3个字节float b;   //4个字节double b;  //8个字节
};             //共20个字节

指定对齐方式(向10对齐)

如果结构体成员大小超过了pack的要求,就按pack来对齐。

如果最大成员大小没有超过pack,就按最大的成员大小来对齐。

#pragma pack(10) //指定向10对齐
struct s6
{char ch1;  //1个字节int ch3;   //4+3个字节float b;   //4个字节double b;  //8个字节
};             //共24个字节

5.typedef关键字

typedef作为c语言关键字,作用是为一种数据类型定义一种新名字。这里的数据类型包括内部数据类型(int,char等),也包含自定义的数据类型(struct等)。

和struct匹配为了代码编写简洁。

和普通变量匹配,通过名字来获取一些信息。

在单片机开发中,经常会看到typedef unsigned char u_int8这样的写法,这样表示就相当于给unsigned char起了一个名字叫做u_int8,能表示的范围是0~255。

和结构体结合通常这样使用:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct s2
{char *ch1;    int ch2;
}STU;                int main()
{   STU student;student.ch2 = 10;student.ch1 = (char *)malloc(128);strcpy(student.ch1,"uyuiy");printf("%d\n",student.ch2);printf("%s\n",student.ch1);return 0;
}

6.结构体常见问题

在定义结构体的时候最容易犯的错误就是定义了一个野指针,然后访问的时候造成段错误。就比如下面这段代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct student
{char *p;
};int main()
{   /*struct student stu;strcpy(stu.p,"sagdh");  这种写法是错误的,p在这里是一个野指针,内存空间没有申请printf("%s\n");         所以应该使用malloc给它安排空间,一定要有空间!*/struct student stu;stu.p=(char *)malloc(128);memset(stu.p,'\0',128);   //把里面每一项都初始化成0strcpy(stu.p,"sagdh");printf("%s\n",stu.p);return 0;
}

C语言——结构体知识点总结相关推荐

  1. c语言结构体定义坐标,C/C++知识点之c语言结构体定义的几种形式

    本文主要向大家介绍了C/C++知识点之c语言结构体定义的几种形式,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助. 1.最常用定义方式:定义结构体data,此时结构体相当于一个类型, ...

  2. C语言结构体详解(结构体定义,使用,结构体大小等)

    c语言结构体详解 1.c语言结构体 1.1 结构体基础知识 1.2 结构体声明 1.3 结构体特殊声明 1.4 结构体的自引用 1.5 结构体的大小的计算 1.5.1了解结构体大小计算规则 1.5.2 ...

  3. C语言结构体——位段概念的讲解

    前言 之前我对结构体内存分配的方式.对默认对齐数的指令修改做了详细的博客讲解,(C语言结构体详解 (2) 结构体内存对齐,默认对齐数,大家有兴趣的话可以去了解了解这方面的知识. 一. 什么是位段? 位 ...

  4. C语言结构体和结构体指针的简单用法

    C语言结构体和结构体指针的简单用法 这里总结一下自己的学习笔记,关于C语言当中的结构体指针的用法,以及结构体简单使用. 简单介绍一下今天出场的嘉宾–>结构体和结构体指针 什么是结构体: 1,定义 ...

  5. c语言结构体教案,结构体——教学设计

    <结构体--教学设计>由会员分享,可在线阅读,更多相关<结构体--教学设计(7页珍藏版)>请在人人文库网上搜索. 1.课堂教学设计表章节名称结构体学科C语言程序设计授课班级大一 ...

  6. c语言 结构体 ppt,C语言结构体ppt课件

    <C语言结构体ppt课件>由会员分享,可在线阅读,更多相关<C语言结构体ppt课件(25页珍藏版)>请在人人文库网上搜索. 1.01,02,03,9.1 结构体,9.2 共用体 ...

  7. c语言结构体语法定义,C | 结构体定义

    话说C语言是很多语言学习的基础,理解并掌握好了C语言的一些语法规则,对于以后学习或者说自学其他语言,可以节省不少的时间.下面我们就来了解C语言程序当中的结构体知识点. 结构体的定义形式如下: stru ...

  8. c语言结构体加联合,C语言:结构体和联合体(共用体)

    结构体:struct 1.结构体变量的首地址能够被其最宽基本类型成员的大小所整除. 2.结构体每个成员相对于结构体首地址的偏移量(offset)都是成员的整数倍. 3.结构体的总大小为结构体最宽基本类 ...

  9. ARM汇编语言实现peek()_ARM汇编之访问C语言结构体数据

    前言 本文的写作目的在于装逼,没有要产生实际价值的意思. 前几天在做编译器的项目,有一个项目团队成员一直在问我ARM汇编能不能读C语言的结构体.我心想,我这生成ARM汇编的代码是用C++写的呀,又不是 ...

最新文章

  1. OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域
  2. verilog设计UART发送接收及各种错误仿真
  3. Oracle入门(十)之概要文件
  4. 【代码真相】之 开篇
  5. html中searchbutton点击没有反应,点击按钮加载完整的HTML后,使用Selenium加载其他元素...
  6. 任正非谈鸿蒙系统问题不大,任正非谈鸿蒙系统:两三年重建生态,有信心打造全球生态...
  7. rabbitmq 消费端代码获取队列名称_RabbitMQ四:生产者--队列--消费者
  8. NRF24L01 + STC15F204EA 无线通信 源代码
  9. Oracle XDB 组件 重建 说明
  10. 我的公司不是家 【联想员工亲历联想大裁员】
  11. 安卓仿苹果音量调节_安卓不仿苹果静音键?千万别小瞧“静音键”, 功能强悍到无敌!...
  12. 【前端领域】3D旋转超美相册(HTML+CSS)
  13. linux LED设备驱动文件
  14. 三星910S3L单m2接口更换硬盘系统克隆全程攻略
  15. mysql内存回收_mysql占用内存过多
  16. 51单片机的指令系统(一)
  17. Unraid 安装百度网盘
  18. 安卓运营商定制手机锁卡方式研究
  19. java日语_java中常用日语词汇整理
  20. 【Linux学习】基础IO

热门文章

  1. 基于MATLAB的离焦模糊图像复原
  2. [乐评]写一点关于我心中的小女人
  3. 《战胜华尔街》书中的精髓:业余投资者如何根据行业特点选好股票,赚得比专业的投资者还要多?
  4. linux 下使用百度云盘
  5. 齐博x1调用栏目分类的字段
  6. 为什么我3岁的儿子有不良信用记录?儿童数据泄露问题暗潮汹涌
  7. 考虑风光火储的微电网优化调度 考虑风电、光伏、热电机组和储能优化调度,其中负荷考虑冬季或夏季两种场景,并且考虑晴天、多云、雨天、多风和少风场景
  8. 张量t-product积基础 | 循环矩阵与向量乘积的离散傅立叶变换 · 循环矩阵的傅里叶对角化
  9. 汽车网络安全之——CAN网关测试
  10. java selector 源码_Java NIO——Selector机制源码分析---转