C语言中细说用typedef和用struct定义结构体的区别及其在单片机C语言开发中的应用

本文主要是介绍C语言中细说用typedef和用struct定义结构体的区别及其在单片机C语言开发中的应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1.struct声明结构体

2.定义结构体变量

3. typedef

(1)采用struct和 typedef struct 声明结构体是有区别的

(2)对比,使用typedef struct 声明结构体

4.GPIO_TypeDef是结构体名称,而不是结构体变量


        typedef和用struct都可以用来定义结构体,采用struct和采用typedef struct 声明结构体是有区别的。

1.struct声明结构体

        结构体是一种自定义的数据类型,可以将不同类型的数据组合在一起,构成一个组合型数据结构。

struct b_type
{uiny32_t _reserved0:27;    /*! bit:0..26 */uiny32_t Q:1;              /*! bit:27 */uiny32_t V:1;              /*! <bit:28 */uiny32_t C:1;              /*! <bit:29 */uiny32_t Z:1;              /*! <bit:30 */uiny32_t N:1;              /*! <bit:31 */
};

        其中,struct是声明结构体的关键字,b_type是结构体的名称。{}里的内容是结构体的成员。在b_type结构体里有6个成员,它们的数据类型都是uint32_t。结构体中各成员的数据类型可以不同。

2.定义结构体变量

        上面的声明的结构体并没有定义结构体变量,只是建立了一个名为b_type的结构体类型。如果仅仅如此,编译的时候,是不会给这个结构体分配存储单元的。

        上面声明的b_type结构体可以通过下面的语句定义变量:

struct b_type b;    // b为结构体变量名

         也可以在声明结构体时定义结构体变量,其效果是相同的:

struct b_type
{uiny32_t _reserved0:27;    /*! bit:0..26 */uiny32_t Q:1;              /*! bit:27 */uiny32_t V:1;              /*! <bit:28 */uiny32_t C:1;              /*! <bit:29 */uiny32_t Z:1;              /*! <bit:30 */uiny32_t N:1;              /*! <bit:31 */
} b;

        此外,在声明结构体时还可以不指定结构体类型名,直接定义结构体变量:

// 直接定义结构体变量GPIO_InitTypeDef
struct
{uint32_t Pin;uint32_t Mode;uint32_t Pull;uint32_t Speed;
} GPIO_InitTypeDef;

        结构体类型和结构体变量是不同的概念,编译时只会对变量分配内存空间,并且只可对变量进行赋值等操作。因此,声明结构体后,如果要使用它,就一定要定义该结构体的变量。

3. typedef

        typedef是C语言中的关键字,它的作用是为其后面的数据类型定义一个“别名”,新的名字。此处所说的其后的数据类型可以是int、char等常用的数据类型,也可以是结构体struct这样的自定义数据类型。使用typedef的目的是简化类型声明,给变量类型定义新名字。

(1)采用struct和 typedef struct 声明结构体是有区别的

        如下,以struct声明了b_type结构体并定义变量b:

struct b_type   // b_type不是变量名,而是结构体名,并且可以省略
{// 类型成员名
} b;            // b是结构体变量

        如果,再定义另一个结构体变量aaa,可以:

struct b_type aaa;

(2)对比,使用typedef struct 声明结构体

typedef struct a_type    // a_type是结构体名称,可以省略
{// 类型 成员名
} a_type_new;            // a_type_new是结构体新的成员名称,不是变量名

        此处,{}后面的a_type_new不再是结构体变量,而是结构体a_type的别名。此时若定义该结构体的变量aaa,可以:

struct a_type aaa;
或
struct a_type_new aaa;

4.GPIO_TypeDef是结构体名称,而不是结构体变量

/*** @brief General Purpose I/O*/typedef struct
{__IO uint32_t MODER;       /*!< GPIO port mode register,               Address offset: 0x00      */__IO uint32_t OTYPER;      /*!< GPIO port output type register,        Address offset: 0x04      */__IO uint32_t OSPEEDR;     /*!< GPIO port output speed register,       Address offset: 0x08      */__IO uint32_t PUPDR;       /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */__IO uint32_t IDR;         /*!< GPIO port input data register,         Address offset: 0x10      */__IO uint32_t ODR;         /*!< GPIO port output data register,        Address offset: 0x14      */__IO uint32_t BSRR;        /*!< GPIO port bit set/reset  register,     Address offset: 0x18      */__IO uint32_t LCKR;        /*!< GPIO port configuration lock register, Address offset: 0x1C      */__IO uint32_t AFR[2];      /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */__IO uint32_t BRR;         /*!< GPIO Bit Reset register,               Address offset: 0x28      */
} GPIO_TypeDef;

        其中,数据类型前面的__IO在固件库中通过define宏定义为volatile:

# define __IO volatile;

        C语言中,变量前加volatile是提醒编译器不用对变量进行优化,调用该变量时,每次都到变量所在寄存器中去读它的内容。

         进一步地,在单片机中,比如在stm32g474xx.h文件中,很多形如GPIO_TypeDef的结构体,都是结构体名称,而不是结构体的变量。

这篇关于C语言中细说用typedef和用struct定义结构体的区别及其在单片机C语言开发中的应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940660

相关文章

CSS3 布局样式及其应用举例

《CSS3布局样式及其应用举例》CSS3的布局特性为前端开发者提供了无限可能,无论是Flexbox的一维布局还是Grid的二维布局,它们都能够帮助开发者以更清晰、简洁的方式实现复杂的网页布局,本文给... 目录深入探讨 css3 布局样式及其应用引言一、CSS布局的历史与发展1.1 早期布局的局限性1.2

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

关于Mybatis和JDBC的使用及区别

《关于Mybatis和JDBC的使用及区别》:本文主要介绍关于Mybatis和JDBC的使用及区别,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、JDBC1.1、流程1.2、优缺点2、MyBATis2.1、执行流程2.2、使用2.3、实现方式1、XML配置文件

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

$在R语言中的作用示例小结

《$在R语言中的作用示例小结》在R语言中,$是一个非常重要的操作符,主要用于访问对象的成员或组件,它的用途非常广泛,不仅限于数据框(dataframe),还可以用于列表(list)、环境(enviro... 目录1. 访问数据框(data frame)中的列2. 访问列表(list)中的元素3. 访问jav

在React聊天应用中实现图片上传功能

《在React聊天应用中实现图片上传功能》在现代聊天应用中,除了文字和表情,图片分享也是一个重要的功能,本文将详细介绍如何在基于React的聊天应用中实现图片上传和预览功能,感兴趣的小伙伴跟着小编一起... 目录技术栈实现步骤1. 消息组件改造2. 图片预览组件3. 聊天输入组件改造功能特点使用说明注意事项

一文教你如何解决Python开发总是import出错的问题

《一文教你如何解决Python开发总是import出错的问题》经常朋友碰到Python开发的过程中import包报错的问题,所以本文将和大家介绍一下可编辑安装(EditableInstall)模式,可... 目录摘要1. 可编辑安装(Editable Install)模式到底在解决什么问题?2. 原理3.

Redis中RedisSearch使用及应用场景

《Redis中RedisSearch使用及应用场景》RedisSearch是一个强大的全文搜索和索引模块,可以为Redis添加高效的搜索功能,下面就来介绍一下RedisSearch使用及应用场景,感兴... 目录1. RedisSearch的基本概念2. RedisSearch的核心功能(1) 创建索引(2

exfat和ntfs哪个好? U盘格式化选择NTFS与exFAT的详细区别对比

《exfat和ntfs哪个好?U盘格式化选择NTFS与exFAT的详细区别对比》exFAT和NTFS是两种常见的文件系统,它们各自具有独特的优势和适用场景,以下是关于exFAT和NTFS的详细对比... 无论你是刚入手了内置 SSD 还是便携式移动硬盘或 U 盘,都需要先将它格式化成电脑或设备能够识别的「文