赋值用|
例:GPIOE_ODR |= 1<<5; //把1赋给了第5位
清零用&
例:GPIOE_ODR &= ~(1<<5); //把第5位清零了
跳过程序1,执行程序2
#ifdef 标识符
程序段 1
#else
程序段2
#endif
防止重复编译
#ifndef 标识符
#define 标识符
程序段
#endif
不编译(跳过编译)
#if 0
程序段 1
#endif
如果标识符被定义过,对程序段1编译,否则对程序段2编译。
选择编译
#if 0
#elif 0
#elif 1
#endif
比如一个变量在另一个文件中被定义,而现在这个文件又要用到它,就需要声明
例:extern int flag;
注:也可以声明函数
例:
typedef struct
{
int a;
char b;
} GP;
typedef unsigned char uchar;
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
#include
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
没超过就按结构体最大的对齐
例:
typedef enum
{
a=1,
b,
c
}ABC;
下面用到a,它就是1(可以理解为替换)
b就是2(因为是按顺序来的,默认b为2,c为3)
uchar a=0x01,b=0x01;
a^=b;
牺牲效率提升正确性
1.volatile直接读取内存
2.一般都是利用线程读取到寄存器,然后CPU读取寄存器数据(寄存器读取速度快);这个时候另一个线程改变了内存值,而寄存器没有改变,就造成了数据错误
1.死循环:
for(;;);
while(1);
2.dowhile比while要多执行一次,不管条件满足与否。
运行Windows命令
指令
1.pause等待用户输入,程序在输入之前不会结束
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)();
1.数组名a就是地址,是数组首地址&a[0]
2.地址传给函数后,是没有元素大小的(多少个)
3.不能直接操作a++,只能定义指针变量,然后指针变量++
char*p
p=a
p++
函数原型void *malloc(size_t size);
用法:int *p=malloc(10);
int *p=(int*)malloc(4*sizeof(int));
内存泄漏:程序崩溃,一直开辟内存不释放
野指针:指向地址不确定
内存释放free();
指针内存初始化p=NULL;
gets()输入
puts()输出,自带换行
strlen()计算字符串长度,不算\0
memset()初始化字符串,复制拼接后用
strcpy()拷贝
strncpy()拷贝个数,写入拷贝2个就复制2个
strcat()拼接
strcmp()比较,
strchr()查找字符,返回字符所在位置地址,没有返回空NULL
strstr()查找字符串
strlwr()转换小写字母
strupr()转换大写字母
strtok()字符串分割,第二次要用NULl第一个参数
int main(int argc,char **argv)
参数1:参数个数
参数2:存放参数内容的二级指针
注:程序名也是一个参数
例:./a aa
argc就是2
argv[0]是./a
argv[1]是aa
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.函数指针,函数名本身就是地址