开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
1、按字节赋值与清零
赋值用| 例:GPIOE_ODR |= 1<<5; //把1赋给了第5位 清零用& 例:GPIOE_ODR &= ~(1<<5); //把第5位清零了
2、ifdef条件编译
跳过程序1,执行程序2 #ifdef 标识符 程序段 1 #else 程序段2 #endif
防止重复编译 #ifndef 标识符 #define 标识符 程序段 #endif
不编译(跳过编译) #if 0 程序段 1 #endif 如果标识符被定义过,对程序段1编译,否则对程序段2编译。
选择编译 #if 0 #elif 0 #elif 1 #endif
3、extern变量声明
比如一个变量在另一个文件中被定义,而现在这个文件又要用到它,就需要声明 例:extern int flag; 注:也可以声明函数
4、typedef类型别名
例: typedef struct { int a; char b; } GP; typedef unsigned char uchar;
5、结构体struct
struct 结构体名{ 成员列表; }变量名列表;变量名列表可以没有,一般没有 定义变量:struct 结构体名字 结构体变量列表; 引用方法:结构体变量名字.成员名 结构体指针变量引用:结构体变量名字->成员名 赋值 结构体a,有3个成员ABC 顺序赋值1给A,2给B,3给C struct a = {1,2,3};
选择赋值1给A,2给C(适用于Linux,keil不能用) struct a = { .A =1, .C =2 };
#include <stdio.h>
#include <string.h>
struct Mcc
{
char data[1024*5];
char cmd[128];
int type;
int set;
};
int main()
{
int i = 100;
struct Mcc a = {
.a = 1,
.data = "xiao",
.cmd = "wei",
};
struct Mcc b = {
.data = "xiaw",
.cmd = "wei",
};
printf("a.data:%s,a.cmd:%s\n",a.data,a.cmd);
i = memcmp(&(a.cmd),&(b.cmd),2);
printf("i=%d",i);
return 0;
}
/*运行结果
a.data:xiao,a.cmd:wei
i=0
*/
结构体大小计算 1.结构体成员的偏移量必须是成员大小的整数倍(0倍认为是任何数的整数倍) 2. 结构体大小必须是所有成员大小(数组,结构体除外)的整数倍。(结构体声明不算进去,但定义了变量就算进去) 3.对齐方式浪费空间,提升计算机访问效率 4.联合体只算占用空间最大的union 5.#pragma pack(10) 结构体最大对齐超过10就按10 没超过就按结构体最大的对齐
8、枚举enum
例: typedef enum { a=1, b, c }ABC; 下面用到a,它就是1(可以理解为替换) b就是2(因为是按顺序来的,默认b为2,c为3)
7、按字节取反(led闪烁)
uchar a=0x01,b=0x01; a^=b;
8、类型修饰符volatile
牺牲效率提升正确性 1.volatile直接读取内存 2.一般都是利用线程读取到寄存器,然后CPU读取寄存器数据(寄存器读取速度快);这个时候另一个线程改变了内存值,而寄存器没有改变,就造成了数据错误
9、循环
1.死循环: for(;;); while(1); 2.dowhile比while要多执行一次,不管条件满足与否。
10、system()
运行Windows命令 指令 1.pause等待用户输入,程序在输入之前不会结束
11、指针
1.for遍历数组指针后,要重新赋值回到数组首地址 int a[10]; int *p; p=a;重新赋地址 2.给一个地址写一个数据 int *p=(int *)0xffe19367; *p=10; 3.指针数组,数组指针 int *p; int(*p)[3]; p=a; printf("%p",++p); 指针数组2个地址相差4 数组指针差4*3 4.函数指针 void (*p)(); p=函数名; 怎么用:p();或者(*p)();
12、数组
1.数组名a就是地址,是数组首地址&a[0] 2.地址传给函数后,是没有元素大小的(多少个) 3.不能直接操作a++,只能定义指针变量,然后指针变量++ char*p p=a p++
15、malloc
函数原型void *malloc(size_t size); 用法:int *p=malloc(10); int *p=(int*)malloc(4*sizeof(int));
14、内存泄漏和野指针
内存泄漏:程序崩溃,一直开辟内存不释放 野指针:指向地址不确定 内存释放free(); 指针内存初始化p=NULL;
15、字符串API
gets()输入 puts()输出,自带换行 strlen()计算字符串长度,不算\0 memset()初始化字符串,复制拼接后用 strcpy()拷贝 strncpy()拷贝个数,写入拷贝2个就复制2个 strcat()拼接 strcmp()比较, strchr()查找字符,返回字符所在位置地址,没有返回空NULL strstr()查找字符串 strlwr()转换小写字母 strupr()转换大写字母 strtok()字符串分割,第二次要用NULl第一个参数
16、main
int main(int argc,char **argv) 参数1:参数个数 参数2:存放参数内容的二级指针 注:程序名也是一个参数 例:./a aa argc就是2 argv[0]是./a argv[1]是aa
17、小细节
1.定义变量要靠近大括号{,不然报错。(放函数开头) 2.一行写不下或写太多不好看用连接符:\(符合前后不能有空格) 3.错误提示中有\243 \254,说明有中文符号 4.加(),不用管什么优先级都加,增加可读性 5.void不是无返回值,是无类型返回值(返回值类型未知) 6.size_t(非负数) 7.int f(),()可以理解成函数,f是函数名,int返回类型 8.结束程序exit(),非0程序异常退出 9.字符串定义了后,就不能直接赋值,只能用拷贝函数strcpy() 10.定义指针后要,分配内存初始化内容,不然就是野指针 11.无返回值函数退出直接return,后面不需要写返回什么 12.结构体变量不能free,否则段错误,malloc的结构体指针删除链表后要free 13.指针要初始化null,所以指针都要null,不然会出现意想不到的问题 14.函数指针,函数名本身就是地址