嵌入式-C语言-江科大-数据类型&宏定义#define&关键字typedef&结构体

发布时间:2024年01月19日

这是C语言中高级相关知识,在单片机中实战的一些用法
参考C语言江科大视频的学习笔记,详细举例子并且完整记录up的想法,包括内容有c语言数据类型&宏定义#define&关键字typedef&结构体&预处理指令

一:C语言数据类型

关键字位数表示范围stdint关键字ST关键字
char8-127-128int_8s8
unsigned char80-255uint8_tu8
short16-32768~32767int16_ts16
unsigned short160~65535uint16_tu16
int32-2147483648~2147483647int32_ts32
unsigned int320~4294967295uint32_tu32
long32-2147483648~2147483647
unsigned long320~4294967295
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
  • 51单片机中int型为16位;stm32中int型为32位。
  • 倒数第二列是C语言给这些类型提供的别名;所以最后一列是老版本ST公司库函数给这些类型提供的别名,新版的库函数已经全部替换成倒数第二列。所以以后尽量使用倒数第二列。

二:宏定义 #define

关键字#define,主要用于:用一个字符串代替一个数字,便于理解,防止出错;或者提取程序中经常出现的参数,便于快速修改。俗称叫外号。

//定义宏定义:
#define ABC 12345
//引用宏定义:
int a = ABC;//相当于int a = 12345;

在这里插入图片描述

  • 相当于GPIO_InitStructure.GPIO_Pin = ((uint16_t) 0x1000)经过宏定义变成GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12;

  • 在C里面,宏定义定义在主函数外面,并且如果给一个变量宏定义一个值,那么程序里面出这个变量都是这个值,并且是不可修改的

三:关键字typedef

关键字typedef,目的将一个比较长的变量类型名换个比较短的变量类型名,便于使用。
因为结构体变量类型较长,所以通常用typedef更改变量类型名。

//定义typedef:
typedef unsigned char uint8_t;
//引用typedef:
uint8_t num1; //等效于unsigned char num1;
  • 相比于#define(不用加分号) 来说,typedef(必须加分号)在进行改名时会进行变量类型检查,如果不是变量类型的名字那是不行的,所以更加安全。
  • 宏定义任何名字都可以换,而typedef只能专门给变量类型换名字。

四:结构体

关键字 struct ,用途:数据打包,是不同类型变量的集合

  • struct c;//一个叫做c的结构体里面有{}
  • struct {char x;int y;float z;}; c; //一个叫做c的结构体里面有{char x;int y;float z;}
//在main函数中定义结构体变量:
struct{      //相当于struct{ int a;} StructName;
	char x;
	int y;
	float z;
}StructName1;
//因为结构体变量类型(结构体也是一个变量类型)较长,
//所以通常在mian函数外用typedef更改变量类型名
typedef  struct{   //相当于(typedef A  a),我把长的变量类型A变为短的变量类型a
	char x;
	int y;
	float z;
}StructName_t; //相当于(typedef struct{}  StructName_t),
				//我把长的变量类型名字struct{}变为短的变量类型名字StructName_t

//引用结构体成员:方法一用‘.’
StructName_t struct1;//我把长的变量类型名字struct{}变为短的变量类型名字StructName_t
//相当于数据类型+变量名字  int a;
struct1.x='A';
struct1.y = 66;
struct1.z = 1.23;
//引用结构体成员:方法二“->”
pStructName ->x = 'A';  //结构体指针名,pStructName为结构体的地址
pStructName ->y = 66;
pStructNmae ->z = 1.23;
  • 数组char a[10]里面有10个char类型的数组元素,都是相同类型的,但我们需要组合10个不同数据类型的呢,那我们可以用结构体,结构体就是不同数据类型的集合。
  • 数组、结构体、共用体、枚举都是构造数据类型
  • 如下图,先定义再引用,int a;a =10;都是数据类型+名字
    在这里插入图片描述在这里插入图片描述

五:枚举类型

关键字enum,enumerate枚举
用途:定义一个取值 受限制的整型变量,也用于限制变量取值范围;
枚举也相当于一个宏定义的集合,可以直接把里面的枚举变量拿出来用。注意枚举变量用逗号隔开,且最后一个枚举变量不加逗号。

//函数内定义枚举变量:
enum{    //enum {} EnumName;
		FALSE = 0,
		TRUE = 1
}EnumName;
//因为枚举变量类型较长,所以通常在函数外用typedef更改变量类型名
typedef enum{
FALSE = 0;
TRUE = 1
}EnumName;

//引用枚举成员:
EnumName emu1;
emu1 =  FLASE;
emu1 =  TRUE;

下图的图一和图二是等价的
在这里插入图片描述在这里插入图片描述

六:预处理指令

#ifndef、#define 和 #endif 来确保头文件只被编译一次。

#ifndef __DELAY_H   //这是预处理指令,用来判断某个宏是否已经定义,如果该宏(没有)定义,则执行下面的代码
#define __DELAY_H  //宏定义

void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);

#endif

当一个头文件(例如delay.h)被多个源文件引用时,可以使用预处理指令 #ifndef、#define 和 #endif 来确保头文件只被编译一次。

#ifndef 预处理指令:
#ifndef 是 “if not defined” 的简写。
#ifndef 用于检查某个宏是否未定义。如果该宏未定义,则执行下面的代码。
如果宏已经定义过了,#ifndef 中的代码将被忽略。

举例子说明:
#endif 是C/C++中的预处理指令,用于结束条件编译块。

当在代码中使用 #ifdef#ifndef#if 这些条件编译指令时,需要使用 #endif
来标记条件编译块的结束位置。

例如,以下是一个简单的条件编译示例:

#ifdef DEBUG_MODE
    // 调试模式下执行的代码
    printf("Debug mode is enabled.\n");
#else
    // 正常模式下执行的代码
    printf("Debug mode is disabled.\n");
#endif 

在这个示例中, #ifdef DEBUG_MODE  判断是否定义了  DEBUG_MODE
宏。如果定义了该宏,则执行调试模式下的代码;否则,执行正常模式下的代码。

最后的 #endif 指令用于标记条件编译块的结束位置。它表示上面的条件编译块已经结束,之后的代码将会被正常编译。

总结来说, #endif  用于结束条件编译块,它与  #ifdef 、 #ifndef  或  #if 
一起使用,确保条件编译的范围正确闭合。

参考:B站STM32江协自动化&【哈工大虎慕】

道友:与其仰望他人,不如埋头奋斗。

文章来源:https://blog.csdn.net/weixin_50833257/article/details/135668186
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。