《C语言结构体史上最详细的讲解》

【结构体类型——详细讲解】 一篇就会让你学懂结构体类型!!! 阅读详情

原文链接

https://github.com/shellhub/blog/issues/40

struct结构体数据类型

前言

我们知道,在C语言中有一些基本的数据类型,如

  • char
  • int
  • float
  • long
  • double
  • string(c99)

等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提供了一种自定义数据类型,他可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct,可以使用struct关键词声明结构体

结构体的声明

结构体的声明语法如下

struct [structure tag] /*结构体的标签*/{

   member definition; /*零个或多个成员变量的定义*/
   member definition;
   ...
   member definition;
} [one or more structure variables];  /*一个或多个结构体变量的定义*/

结构体标签(structure tag)是可选的,但是推荐还是写上,这样使得代码更加规范清晰,成员变量的定义一般为基本数据类型,如 int age; char name[10]等,成员变量之间使用;隔开,最后一个成员变量后面的;可选, 如下面定义一个图书信息的结构体变量

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;  

如下所示

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id
} book;

我省略了最后一个成员变量后面的分号;代码可以正常运行,但是当我使用gcc编译的时候,出现了下面信息

 gcc struct.c

output

struct.c:8:1: warning: no semicolon at end of struct or union
 } book;
 ^

这是警告提示,提示我们需要在struct和union数据类型定义的后面加上分号;,这样的好处就是当我们需要再添加一个成员变量的时候,只需写上该成员变量的定义,而无需先敲;,我太机智了,手动滑稽…

没有成员变量的结构体

我们也可以定义一个空的结构体,有时候我们需要某一个结构体数据类型,但是暂时又不知道如何填充里面的成员变量,我们可以有如下定义

struct Books {
  //TODO
} book;

访问结构体成员

定义完结构体积后接下来就是去访问它并给他赋值,为了访问一个结构体成员变量,我们可以使用成员操作符(.) 成员访问运算符被编码为结构变量名称和我们希望访问的结构成员之间的句点(.)如下所示的完整代码

struct.c

#include <stdio.h>
#include <string.h>

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

int main( ) {

   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */

   /* book 1 specification */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali");
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* book 2 specification */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;

   /* print Book1 info */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);

   /* print Book2 info */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

编译并执行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

结构作为函数参数

同样的,我们也可以像基本数据类型一样,把结构体作为函数的参数,如下所示我们定义一个打印结构体的函数

#include <stdio.h>
#include <string.h>

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

/* function declaration */
void printBook( struct Books book );

int main( ) {

   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */

   /* book 1 specification */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali");
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* book 2 specification */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;

   /* print Book1 info */
   printBook( Book1 );

   /* Print Book2 info */
   printBook( Book2 );

   return 0;
}

void printBook( struct Books book ) {

   printf( "Book title : %s\n", book.title);
   printf( "Book author : %s\n", book.author);
   printf( "Book subject : %s\n", book.subject);
   printf( "Book book_id : %d\n", book.book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

结构体的指针

我们也可以定义结构体指针,像这样

struct Books *struct_pointer;

现在你可以存放结构体变量的地址在结构体变量指针中.和基本数据类型的变量一样,我们使用&操作符取一个变量的地址

struct_pointer = &Book1;

接下来就是使用结构体指针去访问成员变量了,访问的操作符我们由原来的.变为->,没错,这个是不是很形象呢?完整代码如下

#include <stdio.h>
#include <string.h>

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

/* function declaration */
void printBook( struct Books *book );
int main( ) {

   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */

   /* book 1 specification */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali");
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* book 2 specification */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;

   /* print Book1 info by passing address of Book1 */
   printBook( &Book1 );

   /* print Book2 info by passing address of Book2 */
   printBook( &Book2 );

   return 0;
}

void printBook( struct Books *book ) {

   printf( "Book title : %s\n", book->title);
   printf( "Book author : %s\n", book->author);
   printf( "Book subject : %s\n", book->subject);
   printf( "Book book_id : %d\n", book->book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

结构体数组

#include <stdio.h>
#include <string.h>

struct Books {
    char  title[50];
    char  author[50];
    char  subject[100];
    int   book_id;
};

/* function declaration */
void printBook( struct Books *book );
int main( ) {

    struct Books books[2];

    /* book 1 specification */
    strcpy( books[0].title, "C Programming");
    strcpy( books[0].author, "Nuha Ali");
    strcpy( books[0].subject, "C Programming Tutorial");
    books[0].book_id = 6495407;

    /* book 2 specification */
    strcpy( books[1].title, "Telecom Billing");
    strcpy( books[1].author, "Zara Ali");
    strcpy( books[1].subject, "Telecom Billing Tutorial");
    books[1].book_id = 6495700;

    /* print Book1 info by passing address of Book1 */
    printBook( &books[0] );

    /* print Book2 info by passing address of Book2 */
    printBook( &books[1] );

    return 0;
}

void printBook( struct Books *book ) {

    printf( "Book title : %s\n", book->title);
    printf( "Book author : %s\n", book->author);
    printf( "Book subject : %s\n", book->subject);
    printf( "Book book_id : %d\n", book->book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

结构体的内存计算

没错,估计你已经知道了,结构体变量的所占用内存空间的大小为各成员变量所占空间之和,如下所示的结构体占用内存大小在注释里面

#include <stdio.h>
#include <string.h>

struct Books {
};

int main( ) {
    printf("%d\n", (int) sizeof(struct Books)); /*0*/
    return 0;
}
#include <stdio.h>
#include <string.h>

struct Books {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
};

int main() {
    printf("%d\n", (int) sizeof(struct Books)); /*204*/
    return 0;
}

位域

有时候我们内存紧张的时候,我们可以使用位域定义结构体成员变量,比如当我们需要定义一个表示true或false的时候,如果想这样定义

int isOpen;

明显很浪费空间,因为一个真假值只需要一个字位表示,所以我们可以这样定义

unsigned int isOpen:1;

但是如果你直接写在函数中是会报错的,我们应该写在结构体中

int main() {
    unsigned int isOpen:1; /*编译无法通过*/
    return 0;
}

正确姿势

struct packed_struct {
   unsigned int f1:1;
   unsigned int f2:1;
   unsigned int f3:1;
   unsigned int f4:1;
   unsigned int type:4;
   unsigned int my_int:9;
} pack;

C尽可能紧凑地自动打包上述位字段,前提是字段的最大长度小于或等于计算机的整数字长。如果不是这种情况,那么一些编译器可能允许字段存储器重叠,而其他编译器会将下一个字段存储在下一个字中。

#include <stdio.h>
#include <string.h>

struct packed_struct {
    unsigned int f1:1;
    unsigned int f2:1;
    unsigned int f3:1;
    unsigned int f4:1;
    unsigned int type:4;
    unsigned int my_int:9;
} pack;
int main() {
    printf("%d\n", (int) sizeof(struct packed_struct));
    return 0;
}

输出结果
8

C语言——结构体(全) 一、结构体的设计 C语言提供了基本的数据结构,例如 char 、short 、int 、float....等类型;这些偶称为内置类型。怎样设计出来属于自己的类型? 程序员可以使用结构体来封装一些属性,设计出新的类型,在C语言中称为结构体类型。 结构体的定义形式为 struct 结构体名 { 成员列表(可以是基本的数据类型,指针,数组或其他结构类型) }; 举个例子来说吧; 客观事务(实体)是复杂的,要描述它必须从多方面进行;也就是用不同的数据类型来描述不同的方面;用学生实体来说: .. 阅读详情

相关推荐

【C语言】结构类型的定义和使用

结构体(struct)类型;结构标记;typedef;将结构体传入函数;定义结构数组的方法;调用结构数组的方法

小人物,大梦想! 2478

数据结构结构不同,分配的大小不一定一样

<br />#include <stdio.h><br />struct fir<br />{<br />    char a;<br />    int b;<br />    char c<br />}fir;<br />struct tw<br />{<br />    char ab;<br />    char bb;<br />    int  cb<br />}tw;<br />int main(void)<br />{<br />int dd;<br />int cc;<br />dd=si

benico的专栏 1328

安卓-折叠屏平行视界适配(多厂商兼容与优先级实战)

本文详细解析了安卓折叠屏平行视界适配的现状与挑战,重点探讨了多厂商兼容性策略和优先级冲突的实战解决方案。通过对比Google的Embedding方案和国内厂商的EasyGo标准,提供了检测设备支持方案、处理优先级冲突及双方案共存的最佳实践,帮助开发者高效完成折叠屏适配。

weixin_29190169的博客 164

关于RA编译的一些问题记录

1、使用cygwin下载的SDL库文件,存在错误: "Couldn't initialize SDL: No available video device";这个应该是cygwin的库里SDL与操作系统不匹配造成的。 解决方法:先在cygwin中安装一次,然后在http://www.libsdl.org/download-1.2.php上下载”SDL-devel-1.2.15-mingw32

zzcc209的专栏 647

告别环境配置烦恼:用Conda一键搞定GATK4、samtools、fastp等生信分析全家桶

本文介绍如何利用Conda快速搭建包含GATK4、samtools、fastp等工具的生物信息学分析环境,解决软件安装和版本冲突问题。通过详细的配置步骤和实战案例,帮助研究者十分钟内完成重测序分析全家桶的环境配置,显著提升上游分析效率。

weixin_30753873的博客 335

手把手教你用闲置安卓手机+蓝鲸支付,零成本搞定个人项目自动收款(附私有化部署教程)

本文详细介绍了如何利用闲置安卓手机和蓝鲸支付系统,零成本搭建个人项目自动收款解决方案。通过私有化部署教程,读者可以学习到从手机选择、系统配置到支付渠道对接的全流程,实现安全、高效的收款系统,特别适合个人开发者和小型项目使用。

weixin_29597551的博客 335

C语言struct 函数,C语言结构体史上最详细的讲解

原文链接struct结构体数据类型前言我们知道,在C语言中有一些基本的数据类型,如charintfloatlongdoublestring(c99)等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提供了一种自定义数据类型,他可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct,可以使...

weixin_42200829的博客 1万+

ERA5气象数据下载与解压全攻略:Python脚本一键搞定(附错误处理技巧)

本文提供了一套完整的ERA5气象数据自动化处理方案,涵盖从CDS API配置、智能批量下载到高效解压与数据验证的全流程。重点介绍了如何通过Python脚本实现一键式数据下载与批量解压,并分享了实用的错误处理技巧与性能优化策略,帮助科研人员高效获取和处理大规模气象数据。

k8l9m0n的博客 338

c语言事件结构体,C语言结构体史上最详细的讲解

struct结构体数据类型前言我们知道,在C语言中有一些基本的数据类型,如charintfloatlongdoublestring(c99)等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提供了一种自定义数据类型,他可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct,可以使用str...

weixin_39980929的博客 322

PLC1200使用CB1241RS485通讯模块做从站进行Modbus Rtu通信

添加新设备(PLC)->设备和网络管理->点击PLC->看到硬件目录选择通信板->点到点->CB1241(RS485)->看到6ES7241-1CH30-1XB0选择添加,如图。指向Modbus保持寄存器数据块的指针 我这里指向了自定义的DB块数据中一个INT数组。在通信->通信处理模块->MODBUS(选择不带RTU的通信指令块)注意:接线时,TRA接485调试模块的B- TRB接调试模块的A+组态后的硬件标识符 270 对应自己组态后自动生成的。1:事务完成,且无任何错误。波特率对应自己使用的。

swmyaopeng的博客 2万+

突破限制:巧用Azure OpenAI,畅玩Gemini模型

通过 Azure OpenAI 服务这一巧妙的途径,间接调用 Gemini 模型,打破网络限制的壁垒。本文将详细介绍这一方法,无论你是人工智能领域的新手,还是经验丰富的开发者,都能从中获取实用的技巧,轻松开启 Gemini 模型的探索之旅

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 181

c语言在结构体之前定义变量,C语言结构体史上最详细的讲解

struct结构体数据类型前言我们知道,在C语言中有一些基本的数据类型,如charintfloatlongdoublestring(c99)等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提供了一种自定义数据类型,他可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct,可以使用str...

weixin_39956022的博客 325

Response Instance 详解:在 ABAP OData Client Proxy 中读懂每一次响应

ABAP OData Client Proxy中的Response Instance是关键信息载体,封装了业务数据及调用上下文(如分页、delta link等)。响应实例在执行请求后自动生成,根据请求类型返回特定接口(如READ返回/IWBEP/IF_CP_RESPONSE_READ)。响应抽象与OData版本解耦,支持统一处理V2/V4服务。常见响应类型包括单实体读取、列表读取(支持分页和增量同步)、创建/更新/删除响应等。开发时可通过响应对象的安全类型方法获取数据,如get_business_data获

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 138

c语言饿结构_《C语言结构体史上最详细的讲解》

结构体struct · Issue #40 · shellhub/blog​github.comstruct结构体数据类型前言我们知道,在C语言中有一些基本的数据类型,如 char int float long double string(c99)等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提...

weixin_35664081的博客 187

MATLAB地理数据处理 25:植被物候提取及分析模型优化(Savitzky-Golay)

之前我写过一篇使用Savitzky-Golay处理遥感数据,获取地面物候信息的MATLAB代码,但是发现存在一些问题:对物候开始期和物候结束期的阈值设定都为相同值,但是有些研究中,需要根据不同的环境条件,设置不同的物候阈值,所以对其进行相应的修改。

amyniez的博客,欢迎交流讨论 2233

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C语言:结构体(详细讲解)

位段的声明和结构是类似的,有两个不同:1. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他类型。2. 位段的成员名后边有⼀个冒号和⼀个数字。int _b : 5;int main()

qq_67578580的博客 1608

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

关于我终于拿捏了C语言结构体那点事 ——超详细的C语言结构体讲解

这里有超详细的C语言结构体讲解,带你轻松拿捏C结构体

这是一个非常有意思的博主 2561

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C语言指针讲解(史上最全面最经典)

前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析.下面让我们先从简单的类型开始慢慢分析吧: int p; //这是一个普通的整型变量 int * p; //首先从P 处开始,先与结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int

weixin_45041038的博客 4236

C语言指针,这可能是史上最干最全的讲解啦(附代码)!!!

点击上方“大鱼机器人”,选择“置顶/星标公众号”福利干货,第一时间送达!指针对于C来说太重要。然而,想要全面理解指针,除了要对C语言有熟练的掌握外,还要有计算机硬件以及操作系统等方方面面...

张巧龙的博客 8814

C语言结构体总结(详细,直观,全面)

新年必看的一篇结构体文章

weixin_73233099的博客 7242

【初始C语言8】详细讲解初阶结构体的知识

💓作者简介: 加油,旭杏,目前大二,正在学习C++数据结构等👀加油,旭杏的主页👀再识C进阶的专栏👀旭日东升 1👀💖。

加油,考上985的研究生 2537

全面讲解 C 语言的结构体(struct),一网打尽

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删结构体的定义结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。结构体和其他类型基础数据类型一样,例如 int 类型,char类型;只不过结构体可以做成你想要的数据类型,以方便日后的使用。在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新...

轻松学C语言 1万+

【C语言】结构体详细讲解

结构体声明、结构体变量定义及初始化、结构体的自引用、结构体内存对齐、结构体传参、修改默认对齐数

2301_79755897的博客 1269

C语言超详细结构体知识

本文主要介绍了结构体的基本使用,包括创建,声明,初始化,访问操作等,以及结构体如何在内存中进行存储,结构体传参方法优劣,结构体实现位段等知识。

2302_79963723的博客 2320

【C语言】结构体

struct — 结构体的关键字。 student —结构体的标签,可以随意的替换看你指向的对象是谁了。 structstudent ——叫做结构体类型。 大括号 { }里面的内容被称作是:成员变量, 注意大括号后面必须要有分号,可以加成员列表,分号前面内容,可以是全局的结构体变量(一般都不会去使用),在代码中我们要尽可能的去少的使用全局变量。 在函数中 mation —— 结构体类型的变量,当然这里我直接student mation;是可以的,因为我用了typedef关键字,当然这个是可 ......

"謓泽"正在路上朝着"攻城狮"方向"前进四"! 4240

【C语言】——结构体

摘要,写什么好呢?

yusjushd的博客 1846
上一篇: Android网易云历史搜索和热门标签
下一篇: C语言switch史上最详细的讲解
ishellhub
博客等级 码龄9年 102粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值