单片机(C语言)代码基础入门
头文件
<头文件>和"头文件"
- #include <头文件> : 编译器只会从系统配置的库环境中去寻找头文件,不会搜索当前文件夹。 通常用于引用标准库头文件。
- #include "头文件" : 编译器会先从当前文件夹中寻找头文件,如果找不到则到系统默认库环境中去寻找。 一般用于引用用户自己定义使用的头文件。
变量的定义\宏定义
#define
#define定义的标识符常量
宏定义防止使用时错误用小括号包含。
#define 标识符 常量值 //常量
#define TXBUFF_SIZE (128) //发送缓冲大小
//将宏定义做如下修改即可避免溢出问题
#define VOLT_RATE ((long)1000) /*比例系数,强整成 long*/
// 函数
#define ADD(a,b) (a+b)
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) ) //最值
#define WORD_LO(xxx) ((int_8) ((int_16)(xxx) & 255)) //取低位
enum
枚举常量
enum DAY
{
MON = 0, TUE, WED, THU, FRI, SAT, SUN
};
对于没有指定值的枚举元素,其值为前一元素加 1。
关键字
volatile
volatile
是一个关键字,用于告诉编译器,变量的值可能会在程序执行期间被意外地改变,因此编译器不应该对该变量进行优化。
static
静态(static)
static修饰局部变量改变了变量的生命周期,让静态局部变量超出了作用域后依然存在,直到程序结束时,生命周期才结束。
一个函数被static修饰,这个函数就只能在本源文件内使用,不能在其他源文件内使用。
静态全局变量在声明它的文件之外是不可见的,仅在从定义该变量的开始位置到文件结尾可见。
局部变量的值在函数调用结束之后不会消失,仍然保留函数调用结束的值。即它所在的存储单元不释放。 即静态局部变量存储在静态存储区,当静态局部变量离开作用域后,并没有被销毁。当该函数再次被调用的时候,该变量的值为上次函数调用结束时的值。
extern
外部(extern)
const
const修饰的变量不能修改。
用const修饰过的局部变量只是有了「静态特性」,并没有说它变成了「静态变量」。
让逻辑错误在编译期被发现。(无意修改 str[4]='x' 值时,可以编译报错)
struct
结构体
_Bool
布尔类型 bool
typedef
声明定义
typedef struct
{
float temperature; //温度
char humidity; //湿度
char alcohol; //酒精浓度
int illumination;//光照强度
char CO; //一氧化碳浓度
} sensor;
sensor sen;
void
void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。
void真正发挥的作用在于:
(1) 对函数返回的限定;
(2) 对函数参数的限定。
void关键字的使用规则
(1) 如果函数没有返回值,则应声明为void类型;
(2) 如果函数无参数,则应声明其参数为void;
(3) 如果函数的参数可以是任意类型指针,则应声明为其参数为void *;
(4) Void不能代表一个真实的变量;
void * 的使用规则
void *指向的数据类型未定义,
将void *赋值给其它值时需强制类型转换(例1),
但任何类型的指针都可以直接赋(例2)
// 例 1
void *arg;
int i;
i=(int *)arg;
// 例 2
void *p1;
int *p2;
p1 = p2;
-小心使用void *(void指针)
不能对void指针进行算术操作。
void * pvoid;
Pvoid++; //非法
Pvoid--; //非法
int pint;
Pint++; //正确
注:在GNU编译器中,它指定void *的算算术操作于char *算术操作一致,因此在GNU编译器中viod *类型的变量算术运算是正确的。
– 如果函数的参数可以是任意类型指针,则应声明为void *
如我们常用到的:
void * menset(void * buffer,int c,size_t num);
void *mencpy(void *dest,const void *src,size_t len);
将void * 指针缓存区的数据内容存入(数组)内存;
#include <stdio.h>
void * payload;
char *rxbuf;
int main()
{
char a[5] = { 0x01,0x02,0x03,0x04,0x05 };
payload = &a;
printf("a[0] =%x\n", a[0]);
printf("&a =%x\n", &a);
printf("*a =%x\n", *a);
printf("&rxbuf =%x\n", &rxbuf);
rxbuf = (char *)payload;
printf("&rxbuf =%x\n", &rxbuf);
printf("rxbuf[1] =%x\n", rxbuf[1]);
printf("rxbuf[2] =%x\n", rxbuf[2]);
}
功能函数
常用标准库头文件
stdio.h //输入输出
stdlib.h //内存管理,生成随机数
math.h //数学运算
stdbool.h //关键字_Bool可以表示布尔类型。
string.h
//字符串操作
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
知识点
指针
从根本上看,指针是是一个值为内存地址的变量(或数据对象)。指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问。
指针的操作
若已定义:
int a; //定义一个int型的数据
int *p; //定义一个指向int型数据的指针则对指针p有如下操作方式:
& 取地址
如果&运算符左右都有变量,那么这个符号就代表位运算&;
如果&运算符只有右边是变量,那个就代表取地址的意思
* 取内容
如果*运算符左右都有变量,那么这个符号就代表乘法运算符;
int *中的*只是一个标识,一个代号
如果* 只有后面有变量,而前面没有数据类型,那就是取内容,就是解引用的意思
数组与指针
数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于 申请内存、定义指针和初始化
例如: char c[] = {0x33, 0x34, 0x35};
等效于: 申请内存
定义char *c = 0x4000;
初始化数组数据
利用下标引用数据也等效于指针取内容
c[0]; 等效于:*c;
c[1]; 等效于:*c+1;
c[2]; 等效于:*c+2;
(uint8_t *) 表示强制转换成uint8_t类型的指针。
uint8应该是无符号8位二进制整型,其实就是unsigned char类型。
将变量t类型强制转换为uint8 *类型,也就是转换成指向uint8类型变量的指针变量。
字符
将字符串转换为整数
atoi(s1): // atoi(“100”): 转化为整数100
作者:蛋蛋的学习记录