C语言琐碎知识

举报
dz小伟 发表于 2022/11/02 12:21:50 2022/11/02
【摘要】 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...

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.函数指针,函数名本身就是地址

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。