单片机开发工具篇:(五)keil 中常用的 C 语言(简述),stdnt.h、位操作符、条件编译和宏定义、extern 声明、typedef、结构体、指针 - 实践
| 上一篇 | 下一篇 |
|---|---|
| KEIL 与 AC5 和 AC6 | STM32CubeMX 的使用 |
keil 中常用的 C 语言
1)stdint.h
stdint.h 是从 C99 中引进的一个标准 C 库的文件(属于是官方的文件,大部分的厂商都会沿用这个)。
路径:D:\ruanjian\keil5-MDK-ARM\ARM\ARM_Compiler_5.06u7\include\stdint.h
主要内容是:一些宏定义,以及类型别名的重定义。
/* 7.18.1.1 */
/* exact-width signed integer types */
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed __INT64 int64_t;
/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __INT64 uint64_t;
上面代码的间隔或许会误导人,比如第一行,其实是将 signed char 重定义成 int8_t ,后面以此类推。
2)位操作符
位从 0 开始,位 6 就是从右往左数第七个
10 进制和 2 进制互相转换有口诀:8421。每 4 位 2 进制 1111 就是 15 ,且 8(1000)、4(0100)、2(0010)、1(0001)
10 进制和 2 进制的互换明白之后,转成 16 进制就不是问题。
| 运算符 | 含义 | 运算符 | 含义 |
|---|---|---|---|
| & | 按位与 | ~ | 按位取反 |
| | | 按位或 | << | 左移 |
| ^ | 按位异或 | >> | 右移 |
【注意】异或:相同为 0 ,不同为 1 ( 0 和任何数异或都不变,和 1 异或可达到位翻转的效果)。
给某个寄存器或变量某个位赋值(将位 6 赋值为 1 ):
uint8_t temp=0;
temp &= 0XBF; // 方式1.1, 0XBF = 1011 1111
temp &= ~(1<<6); // 方式1.2, ~(1<<6) = 1011 1111
temp |= 0X40; // 方式2.1, 0X40 = 0100 0000
temp |= 1<<6; // 方式2.2, 1<<6 = 0100 0000
3)条件编译和宏定义
① 条件编译
| 指令 | 作用 |
|---|---|
| #if | 编译预处理条件指令,类似 if |
| #ifdef | 判断某个宏是否已被定义 |
| #ifndef | 判断某个宏是否未被定义 |
| #elif | 若前面的条件不满足,则判定新的条件,类似 else if |
| #else | 若前面的条件不满足,则执行后面的语句,类似 else |
| #endif | #if、#ifdef、#ifndef 的结束标志 |
头文件定义示例:
#ifndef _LED_H
#define _LED H
#include "**.h"
code
#endif
代码条件编译:
#if SYS_SUPPORT_OS
code
#endif
② 宏定义
有两种,分别是 常量宏定义 与 函数宏定义 。
常量宏定义:
#define 常量名 常量值 // 例如:#define PI 3.1415926宏名通常用大写字母,以区别于变量。末尾不加分号,否则分号会被替换到代码中导致错误。
函数宏定义:可以通过带参数宏定义来定义函数
#define 宏名(参数列表) 替换文本 // 例如:#define MAX(a, b) ((a)>(b)?(a):(b)) // 取最大值参数和整体表达式需用括号包裹,避免运算符优先级错误。
#define ADD(a,b) a + b(×)。
4)extern 声明
放在函数/变量前,表示此函数/变量在其他文件定义,以便本文件引用。
示例:
extern uint8_t temp;
extern void delay_ms(uint32_t nus);
声明时不可赋值,即 extern uint8_t temp=1; (×)
5)typedef
用于为现有数据类型创建 别名(alias),从而简化复杂类型的声明、提高代码可读性和可维护性。
基本语法:
typedef 原始类型 别名;
示例:
// 基本类型别名
typedef unsigned int uint32; // 将 unsigned int 重命名为 uint32
uint32 a = 10; // 等价于 unsigned int a = 10;
//结构体类型简化
typedef struct {
int x;
int y;
} Point; // Point现在是结构体类型别名
Point p1; // 直接使用别名声明变量
//指针类型简化
typedef int* IntPtr; // 将int指针类型重命名为IntPtr
IntPtr p = &a; // 等价于 int* p = &a;
//数组类型简化
typedef int IntArray[10]; // 将包含10个int的数组类型重命名为IntArray
IntArray arr; // 等价于 int arr[10];
//...等等
6)结构体
定义语句:
//第一种写法:
struct 结构体名
{
成员列表;
...
}实例列表(可选);
//第二种写法:
struct 结构体名
{
成员列表;
...
};
struct 结构体名 实例1,实例2;
上述代码中,实例列表就是这个结构体的实例。
例如:
struct student
{
uint_8 age;
uint_8 sorce;
...
} stu1,stu2;
其中 stu1 和 stu2 就是实例,可以通过 . 来访问元素:stu1.age 、stu2.sorce 。
如果使用 typedef 重定义的话,则是:
typedef struct
{
成员列表;
...
}结构体名;
结构体名 实例1,实例2; // 就不需要在前面写 struct 了
注意:结构体指针使用 -> 来访问元素(和C++一样)。
7)指针
C++ 那里的笔记仔细总结过了,这里就不再解释了。

浙公网安备 33010602011771号