STM32的GPIO输入和输出函数详解

系列文章目录

STM32单片机系列专栏

C语言术语和结构总结专栏

文章目录

1. GPIO模式

2. GPIO输出

2.1 RCC

2.2 GPIO

3. 代码示例

3.1 RCC时钟

3.2 GPIO初始化

3.3 GPIO输出函数

3.4 推挽输出和开漏输出

4. GPIO输入

4.1 输入模式

4.2 数据读取函数

5. C语言语法


1. GPIO模式

GPIO是微控制器中最基本也是最灵活的功能之一,其可以被配置为输入或输出模式,以及许多其他特殊功能模式。通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式:

模式名称类型描述
浮空输入浮空输入引脚没有内部或外部上拉或下拉,其电平未定义,通常不建议使用
上拉输入上拉输入引脚内部上拉至VDD,外部信号低于VDD时,检测到低电平
下拉输入下拉输入引脚内部下拉至VSS,外部信号高于VSS时,检测到高电平
模拟输入模拟输入GPIO未锁定,引脚直接连接到内部ADC
开漏输出开漏输出引脚以开漏模式工作,高电平时为高阻态,低电平时连接到VSS
推挽输出推挽输出引脚以推挽模式工作,高电平时连接到VDD,低电平时连接到VSS
复用开漏输出复用开漏输出用于复用功能的开漏输出,高电平时为高阻态,低电平时连接到VSS
复用推挽输出复用推挽输出用于复用功能的推挽输出,高电平时连接到VDD,低电平时连接到VSS

模式分类:

  • 输入模式(Input):引脚被配置为输入,用来读取外部信号的状态。
  • 输出模式(Output):引脚被配置为输出,可以驱动外部设备或显示设备状态。

类型分类:

  • 推挽输出(Push-pull):可以在两种状态之间切换,要么连接到VDD(高电平),要么连接到VSS(低电平)。
  • 开漏输出(Open-drain):只能连接到VSS(低电平),而高电平状态需要外部拉高。

GPIO配置说明

  • 浮空输入(Floating input):引脚没有内部或外部的上拉或下拉电阻,状态由外部电路决定。
  • 上拉输入(Pull-up input):引脚内部连接有上拉电阻,如果外部电路没有连接,它将读取为高电平。
  • 下拉输入(Pull-down input):引脚内部连接有下拉电阻,如果外部电路没有连接,它将读取为低电平。
  • 模拟输入(Analog input):GPIO以模拟方式工作,可以直接连接到内部ADC(模拟到数字转换器)。
  • 开漏输出(Open-drain output):引脚在激活时连接到VSS,非激活时不连接(悬空)。常用于需要外部拉高的应用场合。
  • 推挽输出(Push-pull output):引脚可以输出高电平(连接到VDD)或低电平(连接到VSS)。
  • 复用开漏输出(Alternate function open-drain output):开漏输出,但是引脚被配置为特殊功能,例如I2C通信。
  • 复用推挽输出(Alternate function push-pull output):推挽输出,但是引脚被配置为特殊功能,例如PWM输出。

2. GPIO输出

操作STM32的GPIO一共有三个步骤:

  1. 使用RCC开启GPIO的时钟
  2. 使用GPIO_Init函数初始化GPIO
  3. 使用输出或者输入函数控制GPIO

2.1 RCC

首先打开一个新建好的工程文件,如果不知道怎么建立工程文件,可以看下面这篇文章:

使用Keil MDK创建STM32标准库工程

之后在Library中找到rcc.h文件(这里全程使用vscode去操作,如果不知道怎么实现Keil和VSCode协同开发STM32程序,可以查看下面这篇教程:

Keil和VSCode协同开发STM32程序

在rcc.h文件中拖到最下面,这里一般都是所有库函数的声明,这里最常用的就是这三个函数:

void RCC_AHBPeriphClockCmd:外设时钟控制

接着选择函数名,右键并选择转到定义(这里需要先进行一次编译,否则可能无法跳转) ,之后会来到.c文件的函数定义,下面解释一下这个函数:

// 函数定义:控制特定AHB外设的时钟。
// RCC_AHBPeriph:要配置的AHB外设。
// NewState:指定外设时钟的新状态,ENABLE(使能) 或 DISABLE(失能)。
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
  // 确保输入参数RCC_AHBPeriph是预定义的有效外设。
  assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
  
  // 确保输入的NewState是有效的功能状态(ENABLE 或 DISABLE)。
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  // 如果NewState不是DISABLE(即是ENABLE),执行以下代码。
  if (NewState != DISABLE)
  {
    // 通过逻辑或运算将对应的位设置为1,来使能(开启)外设的时钟。
    RCC->AHBENR |= RCC_AHBPeriph;
  }
  // 如果NewState是DISABLE,执行以下代码。
  else
  {
    // 通过逻辑与运算与对应位的否定值运算,将对应的位设置为0,来禁能(关闭)外设的时钟。
    RCC->AHBENR &= ~RCC_AHBPeriph;
  }
}

2.2 GPIO

下面看一下GPIO.h的文件,在Library中找到GPIO.h文件,也是拖到最后,这里可以看到常用的函数。

void GPIO_DeInit(GPIO_TypeDef* GPIOx);
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

void GPIO_DeInit(GPIO_TypeDef* GPIOx);
功能:将指定GPIO端口的所有配置重置为默认值。
参数:GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
说明:这个函数通常用于在重新配置(复位)GPIO端口之前清除端口的当前配置。


void GPIO_AFIODeInit(void);
功能:将AFIO(Alternate Function IO)模块的所有配置重置(复位)为默认值。
说明:这个函数通常用于清除所有GPIO端口的复用功能配置。


void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能:用结构体的参数初始化指定GPIO端口的引脚。
参数:

  • GPIOx:要初始化的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_InitStruct:包含了初始化配置的结构体指针,如引脚模式、输出类型、输出速度等。

说明:这个函数用于配置GPIO引脚的各种属性,例如输入/输出模式、输出类型、输出速度等。


void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
功能:将给定的GPIO_InitTypeDef结构体初始化为默认值。
参数:GPIO_InitStruct:要初始化的GPIO_InitTypeDef结构体指针。
说明:这个函数用于在配置GPIO引脚之前,将相关的结构体初始化为默认值。


uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

功能:读取指定GPIO端口指定引脚的输入状态。
参数:

  • GPIOx:要读取的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要读取的引脚,可以是单个引脚或多个引脚的按位或组合。

返回值:引脚的输入状态,0/1。或者GPIO端口的输入状态,每个引脚的状态对应一个位。


void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:将指定GPIO端口指定引脚的输出状态设置为高电平。
参数:

  • GPIOx:要设置的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要设置的引脚,可以是单个引脚或多个引脚的按位或组合。

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:将指定GPIO端口指定引脚的输出状态设置为低电平。
参数:

  • GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要重置的引脚,可以是单个引脚或多个引脚的按位或组合。

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
功能:将指定GPIO端口指定引脚的输出状态设置为指定的电平。
参数:

  • GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要写入的引脚,可以是单个引脚或多个引脚的按位或组合。
  • BitVal:要设置的电平,可以是Bit_RESET(低电平)或Bit_SET(高电平)。

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
功能:设置指定GPIO端口的输出状态。
参数:

  • GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
  • PortVal:要设置的输出值,每个引脚的状态对应一个位,0表示低电平,1表示高电平。

3. 代码示例

这里使用最基础的led灯来解释代码功能

3.1 RCC时钟

main.c文件中,首先调用RCC中的APB2外设时钟控制函数,首先和刚才一样,在RCC.h找到函数名, RCC_APB2PeriphClockCmd, 复制到main中,接着右键函数转到定义,根据注释中的提示,因为点亮的是PA0的LED,所以选择 RCC_APB2Periph_GPIOA,将其放到第一个参数,第二个参数选择ENABLE, 这样时钟就开启了。

 

3.2 GPIO初始化

接着调用GPIO的初始化函数,在GPIO.h中找到 GPIO_Init 函数,跳转到定义,和rcc类似根据注释中的提示,第一个参数选择GPIOA, 第二个参数是一个结构体

先把结构体复制到GPIO_Init上面,起名为:GPIO_InitStructure, 这个结构体相当于一个局部变量,然后将结构体的成员都列出来,如下所示:

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = ;
	GPIO_InitStructure.GPIO_Mode = ;
	GPIO_InitStructure.GPIO_Speed = ;
	GPIO_Init()

接下来就是如何根据标准库文件来配置函数,以GPIO_Mode为例, 接下来会详细到每一个操作,之后这些操作会省略。

  • 首先右键 GPIO_Mode转到定义

  • 根据提示,我们选择GPIOMode_TypeDef,接着按ctrl+f 搜索,在下面找到定义方式,这里有GPIO的八种工作模式。

  • GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)
  • GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)
  • GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)
  • GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)
  • GPIO_Mode_Out_OD (0x14):开漏输出模式(Open-Drain Output Mode)
  • GPIO_Mode_Out_PP (0x10):推挽输出模式(Push-Pull Output Mode)
  • GPIO_Mode_AF_OD (0x1C):复用开漏输出模式(Alternate Function Open-Drain Mode)
  • GPIO_Mode_AF_PP (0x18):复用推挽

因为这里是为了实现LED功能,所以使用GPIO_Mode_Out_PP,将其复制到GPIO_Mode后面。

接着是GPIO_Pin,同样的操作,转到定义,这里很简单,选择GPIO_Pin_0即可。

  • 如果要使用多个A引脚,例如多个led灯,直接在后面加上即可,每个定义之间用 | 隔开。

最后是GPIO_Speed,转到定义以后,按ctrl+f 搜索,如图所示下一个就是函数说明,这里选择GPIO_Speed_50MHz,将其复制到GPIO_Speed后面。

最后,将完成配置的结构体的变量名:GPIO_InitStructure,复制到GPIO_Init中即可完成GPIO的初始化配置。

此时,main.c中的代码如下:

#include "stm32f10x.h"                  // Device header

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		
	}
}

3.3 GPIO输出函数

完成GPIO的初始化之后,就可以使用GPIO的输出函数了,四个输出函数为(前面已经解释):

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//将指定GPIO端口指定引脚的输出状态设置为高电平。
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//将指定GPIO端口指定引脚的输出状态设置为低电平。
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
//将指定GPIO端口指定引脚的输出状态设置为指定的电平。
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
//设置指定GPIO端口的输出状态。

GPIO_ResetBits

我们选择低电平输出,所以使用 GPIO_ResetBits,和前面的操作一样,可以转到定义查看注释说明,因为led灯使用A0引脚,所以代码为:

	GPIO_ResetBits(GPIOA, GPIO_Pin_0);

此时下载程序到单片机中就可以看到LED灯已经被点亮。(注意这里采用的时led长脚连接负极,短接连接引脚,代表低电平点亮)

GPIO_SetBits

如果换成 GPIO_SetBits,可以发现LED熄灭,因为此时输出为高电平。

GPIO_WriteBit

第三种输出函数:GPIO_WriteBit,这个函数是指定输出类型,比如前面的配置不同改变,多了一个BitAction参数,转到定义,可以发现注释教程中说明了两个方式Bit_RESETBit_SET

Bit_RESET: 清除端口值(置低电平)

Bit_SET: 设置端口值(置高电平)

GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led点亮。。GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led熄灭。

目前main.c中的代码如下:

#include "stm32f10x.h"                  // Device header

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);

	while (1)
	{
		
	}
}

这里的GPIO_WriteBit用于LED点亮时,可能会发现一个问题,Bit_SET可以置为高电平,此时LED熄灭,那如果想用基本的0和1来代表高低电平,直接将Bit_SET改为1会出现警告,所以还需要加上强制类型转换,把1和0类型转为BitAction的枚举类型:

GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);

这就是GPIO输出函数的配置,之后就是你想实现的功能,这些功能就是在后面的while中去实现,并且根据不同的模块和功能添加不同的库,例如实现led连续闪烁,除了修改main.c中的主程序,还需要在工程文件在加入delay.c 和 delay.h 文件。但操作都类似,在.h文件中找到需要使用的标准库函数,转到定义在.c文件中找到函数定义和注释说明。

GPIO_WriteBit

这个函数可以设置指定GPIO端口的输出状态。例如对于多个led的控制。

首先还是转到定义,从注释中可以看到,第一个参数依然是GPIOA, 第二个参数是指定写到输出数据寄存器的值,下面可以看到第二个参数是直接写道GPIO和ODR寄存器里的。

所以可以直接写0x001(十六进制),对应二进制为0000 0000 0000 0001。这16个二进制分别对应PA0 - PA15 一共16个端口,最低位(右边)对应PA0。

此时如果加入延迟函数,就可以实现最基本的led灯流水线

#include "stm32f10x.h"                  // Device header

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	while (1)
	{
		GPIO_Write(GPIOA, 0x0001); // Set PA0
		Delay_ms(1000);
		GPIO_Write(GPIOA, 0x0002); // Set PA1	
		Delay_ms(1000);
		GPIO_Write(GPIOA, 0x0004); // Set PA2
		Delay_ms(1000);
	}
}

如果设置为低电平触发,可以在参数前加上 ~ ,意思是取反。

3.4 推挽输出和开漏输出

对于推挽输出和开漏输出的驱动问题,还是用刚才led的例子,目前我们使用的是GPIO_Mode_Out_PP (0x10):推挽输出模式。此时将led短脚连接负极,长接连接引脚,代表高电平点亮,这时可以发现程序依然可用,说明在推挽模式下,高低电平都有驱动能力。

如果把端口的模式改为 GPIO_Mode_Out_OD (0x14):开漏输出模式

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

此时led还是保持高电平点亮,但程序不起作用,只有当led引脚切换以后,改为低电平点亮时,程序才可以正常运行,这说明开漏输出模式的高电平不具有驱动能力。

所以,推挽输出高低电平都有驱动能力,开漏输出高电平相当于高阻态,没有驱动能力,只有低电平有驱动能力。

4. GPIO输入

4.1 输入模式

GPIO输入的配置和GPIO输出类似,不同的数结构体中 GPIO_InitStructure.GPIO_Mode 不同,这里要使用下面的四种输入模式,例如按键输入使用上拉输入模式(GPIO_Mode_IPU)

GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)

  • 在这种模式下,GPIO引脚被配置为读取模拟信号,意味着它可以直接与微控制器内部的模拟-数字转换器(ADC)相连。
  • GPIO引脚不会被数字输入缓冲器干扰,这样可以保证模拟信号的准确性和质量。
  • 通常用于传感器信号读取,如温度、压力或湿度传感器。

GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)

  • GPIO引脚配置为数字输入,没有激活内部上拉或下拉电阻,其电平状态取决于外部电路。
  • 如果外部没有提供确定的电平,引脚的状态是未定义的,可能会浮动,因此称为“浮空”。
  • 这种模式适合于外部电路总是会驱动GPIO到一个确定状态,或者外部已经提供了必要的上拉或下拉设置。

GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)

  • PIO引脚配置为数字输入,并且内部激活了下拉电阻,这会将引脚默认拉至低电平(接地)。
  • 如果外部没有提供信号,引脚将读取为低电平状态;如果外部提供了高电平信号,则会被检测到。
  • 这种模式适用于按钮或开关,其中未激活状态需要确保为低电平。

GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)

  • GPIO引脚配置为数字输入,并且内部激活了上拉电阻,这会将引脚默认拉至高电平(接VDD或正电源)。
  • 如果外部没有提供信号,引脚将读取为高电平状态;如果外部提供了低电平信号,则会被检测到。
  • 这同样适用于按钮或开关,但在这种情况下,未激活状态需要确保为高电平。

4.2 数据读取函数

还有GPIO数据读取的函数:例如读取按键输入就要用到 GPIO_ReadInputDataBit

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

  • 功能:此函数用于读取STM32的GPIO端口上的单个输入引脚的状态。这对于检测如按钮按下、限位开关触发等简单的二进制输入非常有用。
  • 参数
    • GPIOx:指向你想要读取的GPIO端口的指针。STM32微控制器有多个GPIO端口,例如GPIOA、GPIOB等,每个都对应不同的物理引脚组。
    • GPIO_Pin:具体的GPIO引脚编号,它是一个16位的值,每一位代表一个特定的引脚。例如,如果你想读取第0位,就会使用GPIO_Pin_0
  • 返回值:返回值是一个8位的无符号整数。如果指定的引脚处于高电平状态,则返回非零值;如果处于低电平,则返回零。

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

  • 功能:这个函数读取整个GPIO端口的当前输入数据。这在你需要同时检查一个端口上的多个引脚状态时非常有用。
  • 参数
    • GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向要读取的GPIO端口的指针。
  • 返回值:返回值是一个16位的无符号整数。每个比特位代表该端口上对应引脚的输入状态,位值为1表示该引脚处于高电平,位值为0表示处于低电平。

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

  • 功能:此函数用于读取STM32的GPIO端口上的单个输出引脚的状态。这在你需要确认引脚的当前输出状态,例如,确保一个LED是否被程序正确控制时非常有用。
  • 参数
    • GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向你想要读取的GPIO端口的指针。
    • GPIO_Pin:与GPIO_ReadInputDataBit函数中的GPIO_Pin相同,表示特定的GPIO引脚编号。
  • 返回值:返回值是一个8位的无符号整数。如果指定的引脚正在输出高电平,则返回非零值;如果正在输出低电平,则返回零。

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

  • 功能:这个函数读取整个GPIO端口的当前输出数据。当你需要审核或调试一个端口上多个引脚的输出配置时,这个函数非常有用。
  • 参数
    • GPIOx:与GPIO_ReadInputData函数中的GPIOx相同,指向要读取的GPIO端口的指针。
  • 返回值:返回值是一个16位的无符号整数。与GPIO_ReadInputData类似,每个比特位代表该端口上对应引脚的输出状态,位值为1表示该引脚正在输出高电平,位值为0表示正在输出低电平。

5. C语言语法

STM32基于C语言开发,对于这部分,需要有一些C语言的基础知识,例如下面的数据类型,如果对这方面不太了解,可以看下面的C语言系列讲解。

C语言语法和结构总结系列专栏

数据类型位数表示范围stdint定义ST定义
char8-128 ~ 127int8_ts8
unsigned char80 ~ 255uint8_tu8
short16-32768 ~ 32767int16_ts16
unsigned short160 ~ 65535uint16_tu16
int32-2147483648 ~ 2147483647int32_ts32
unsigned int320 ~ 4294967295uint32_tu32
long32-2147483648 ~ 2147483647int32_ts32
unsigned long320 ~ 4294967295uint32_tu32
long long64-(2^64)/2 ~ (2^64)/2-1int64_t
unsigned long long640 ~ (2^64)-1uint64_t
float32-3.4e38 ~ 3.4e38
double64-1.7e308 ~ 1.7e308

接下来对几个关键的语法进行简单说明:

宏定义  #define

用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改。

定义宏定义:

  #define test 123

引用宏定义:

  int a = test;  //等效于int a = 123;

typedef 

用途:将一个比较长的变量类型名换个名字,便于使用,只能用于变量名。
定义typedef:

 typedef unsigned char uint8_t;

引用typedef:

uint8_t a;    //等效于unsigned char a;

结构体  struct
用途:数据打包,不同类型变量的集合
定义结构体变量:因为结构体变量类型较长,所以通常用typedef更改变量类型名

struct{char x; int y; float z;} StructName;

引用结构体成员:

StructName.x = 'T';
StructName.y = 123;
StructName.z = 55.55;
//或者
pStructName->x = 'T'; //pStructName为结构体的地址    
pStructName->y = 123;
pStructName->z = 55.55;

枚举 enum

用途:定义一个取值受限制的整型变量,用于限制变量取值范围;宏定义的集合.
定义枚举变量:因为枚举变量类型较长,所以通常用typedef更改变量类型名

enum{FALSE = 0, TRUE = 1} EnumName;

引用枚举成员:

EnumName = FALSE;
EnumName = TRUE;

这里知识简单说明,如果想要深入学习,可以看下面的C语言系列讲解。

C语言语法和结构总结系列专栏
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/568984.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024免费最好用的苹果电脑mac虚拟机工具Parallels Desktop19中文版下载

一、软件概述 Parallels Desktop是一款专为Mac设计的虚拟机软件,它允许用户在Mac上同时运行Windows、Linux等多个操作系统,而无需额外的硬件设备。通过Parallels Desktop,Mac用户可以轻松地在同一台电脑上体验不同操作系统的功能和应用程序。…

Burpsuite CA证书导入浏览器、导入本地

前言 为什么要导入证书,因为要获得浏览器的信任、本地的信任;才能抓包 导入浏览器 1.从bp导出证书 然后打开火狐浏览器 打开bp,设置好代理 火狐浏览器foxyproxy开启代理 访问https://www.baidu.com 可以抓到https的包 本地导入CA证书 可能某一天你要…

AIGC实战——基于Transformer实现音乐生成

AIGC实战——基于Transformer实现音乐生成 0. 前言1. 音乐生成的挑战2. MuseNet3. 音乐数据3.1 巴赫大提琴组曲数据集3.2 解析 MIDI 文件3.3 分词3.4 创建训练数据集 4. MuseNet 模型4.1 正弦位置编码4.2 多输入/输出 5. 音乐生成 Transformer 的分析6. 多声部音乐分词6.1 网格…

牛客NC195 二叉树的直径【simple DFS C++ / Java /Go/ PHP】

题目 题目链接: https://www.nowcoder.com/practice/15f977cedc5a4ffa8f03a3433d18650d 思路 最长路径有两种情况: 1.最长条路径经过根节点,那么只需要找出根节点的左右两棵子树的最大深度然后相加即可。 2.最长路径没有经过根节点&#xf…

JavaSE——常用API进阶二(8/8)-Arrays、Comparable、Comparator(Arrays类提供的的常见方法、用法示例)

目录 Arrays Arrays类提供的的常见方法 用法示例 Comparable、Comparator Comparable Comparator 本篇学习Arrays,不算作是重点知识,但是为学习后面的Lambda表达式打一个基础,或者说,作为铺垫。 Arrays 用来操作数组的一个…

初见-响应式编程-002

🤗 ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace #Reacti…

lnmp架构

目录 环境 步骤 下载nginx源码包,并解压 安装依赖包 进行预编译 、编译安装 安装php、设置开机自启 配置nginx让其支持php服务 浏览器测试 安装mariadb 部署discuz论坛 简介 LNMP架构是一种常见的Web服务器架构,由Linux、Nginx、MySQL和PHP组成。它…

高级数据结构—线段树(一)

学线段树的原因是因为cf的一道题目始终想不出来怎么优化,后来知道区间查询和修改要用到线段树。。。 原题:Iva & Pav 线段树的作用 区间最值查询:可以高效地找到给定区间内的最大值、最小值等。 区间和查询:可以高效地计算…

Leetcode算法训练日记 | day34

专题九 贪心算法 一、K次取反后最大化的数组和 1.题目 Leetcode:第 1005 题 给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个…

关于Spring事务管理之默认事务间调用问题

由事务的传播行为我们知道, 如果将方法配置为默认事务REQUIRED在执行过程中Spring会为其新启事务REQUIRES_NEW, 作为一个独立事务来执行. 由此存在一个问题。 如果使用不慎, 会引发org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back bec…

ACE框架学习

目录 ACE库编译 ACE Reactor框架 ACE_Time_Value类 ACE_Event_Handler类 ACE定时器队列类 ACE_Reator类 ACE Reactor实现 ACE_Select_Reactor类 ACE_TP_Reactor类 ACE_WFMO_Reactor类 ACE库编译 首先去ACE官网下载安装包,通过vs2017或者2019进行编译&#x…

【洛谷 P8605】[蓝桥杯 2013 国 AC] 网络寻路 题解(图论+无向图+组合数学)

[蓝桥杯 2013 国 AC] 网络寻路 题目描述 X X X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种…

10.接口自动化测试学习-Pytest框架(2)

1.mark标签 如果在每一个模块,每一个类,每一个方法和用例之前都加上mark标签,那么在pytest运行时就可以只运行带有该mark标签的模块、类、接口。 这样可以方便我们执行自动化时,自主选择执行全部用例、某个模块用例、某个流程用…

数据分析专家能力模型

招式:懂商业(业务能力) 外功更偏重于技能,首先需要懂招式,即懂商业,数据分析最终是为业务服务的,无论是互联网企业准求的用户增长和UJM分解,还是传统企业追求的降本增效和精细化运营…

appium相关的知识

>adb shell dumpsys window | findstr mCurrentFocus adb devices # 实例化字典 desired_caps = dict() desired_caps[platformName] = Android desired_caps[platformVersion] = 9 # devices desired_caps[deviceName] = emulator-5554 # 包名 desired_caps[appPackage] …

重建大师出现“密集匹配失败”的情况是什么原因?

答:一般出现密集匹配失败的情况,就是瓦块连接点过少,空瓦块边缘瓦块等原因导致。遇见这种情况,确定是边缘瓦块导致后,就可以不用管,不是模型主体,不影响成果。 重建大师是一款专为超大规模实景三…

MySQL__索引

文章目录 😊 作者:Lion J 💖 主页: https://blog.csdn.net/weixin_69252724 🎉 主题: MySQL__索引) ⏱️ 创作时间:2024年04月23日 ———————————————— 索引介绍…

消消乐算法总结

前言 最近在工作中遇到一个问题,做一个消消乐的demo项目,连续相同数目超过四个后就要消除。我在网上看了很多解决方案,有十字形,横向,纵向,梯形搜索。越看越迷糊。这不是用一个BFS就能解决的问题吗&#x…

MySQL数据库进阶篇一(存储引擎、索引)

目录 一、存储引擎1.1、MySQL体系结构:连接层,Server层,引擎层,存储层1.2、存储引擎1.2.1、存储引擎:InnoDB(MySQL 5.5后默认的存储引擎)1.2.2、存储引擎:MyISAM (MySQL早期默认存储引擎)1.2.3、存储引擎&a…

数据可视化———Tableau

基本认识: 维度:定性—字符串文本,日期和日期时间等等 度量:定量—连续值,一般属于数值 数据类型: 数值 日期/日期时间 字符串 布尔值 地理值 运算符 算数运算符:加减乘除,%取余,…
最新文章