文章目录
嵌入式学习Day05
宏定义
用法
定义 : #define 宏名 常量
作用 :在程序中可以使用宏名替代常量
规范:宏名一般用大写
#include<stdio.h>
/*宏定义*/
#define NAME "LiMing"
int main(){
//使用宏定义
printf("NAME 被定义为 %s \n",NAME);
}
root@wangjudealy:/learn# gcc 0317.c
root@wangjudealy:/learn# ./a.out
NAME 被定义为 LiMing
宏函数
定义:#define 宏函数名 函数体
注意:宏的作用是原样替换
#include<stdio.h>
/*宏定义*/
#define NAME "LiMing"
/*宏函数*/
#define FUN(x) (x*x)
int main(){
//使用宏函数
printf("result = %d \n",FUN(10+10));//因为宏是原样替换,所以此处实际代码为: 10+10*10+10 结果为120
printf("result = %d \n",FUN(20));
}
root@wangjudealy:/learn# ./a.out
result = 120
result = 400
do while(0) 在嵌入式中的应用
作用:
- 代码只执行一次,防止使用宏时报错
- 可以扩展宏定义
不使用do while(0)
#include<stdio.h>
void f1(){
printf("this is fu1\n");
}
void f2(){
printf("this is fu2\n");
}
void f3(){
printf("this is fu3\n");
}
#define TEST() f1();f2();
int main(){
int p =0;
printf("请输入p:\n");
scanf("%d",&p);
if(p>1)
TEST(); //因为宏是原样替换,所以此处相当于执行了两句 f1();f2();
//此时程序编译就会报错,因为如果不加{},if 后只能跟随一句
else
f3();
return 0;
}
root@wangjudealy:/learn# vi 0317.c
root@wangjudealy:/learn# gcc 0317.c
0317.c: In function ‘main’:
0317.c:21:2: error: ‘else’ without a previous ‘if’
21 | else
| ^~~~
使用do while(0)
#include<stdio.h>
void f1(){
printf("this is fu1\n");
}
void f2(){
printf("this is fu2\n");
}
void f3(){
printf("this is fu3\n");
}
#define TEST() do{\
f1();\
f2();\
if(1){\
printf("其他扩展部分\n");\
}\
}while(0)
//注意:因为是原样替换,所以while(0)后没有;
int main(){
int p =0;
printf("请输入p:\n");
scanf("%d",&p);
if(p>1)
TEST(); //因为宏是原样替换,所以此处相当于执行了两句 f1();f2();
//此时程序编译就会报错,因为如果不加{},if 后只能跟随一句
else
f3();
return 0;
}
root@wangjudealy:/learn# gcc 0317.c
root@wangjudealy:/learn# ./a.out
请输入p:
12
this is fu1
this is fu2
其他扩展部分
条件编译
格式:#if 宏名
语句1
#else
语句2
#endif
作用:判断宏名是否为真(0为假,其他值为真),已定义执行语句1,否则执行语句2。
格式:#ifndef 宏名
语句
#endif
作用:判断宏名是否存在,不存在则执行语句,否则不执行
#ifndef===> if no define,同理,也有 #ifdef
C语言多文件编程
extern关键字
格式
功能:使全局变量、函数可以扩展到其他文件中使用
格式1(修饰全局变量):extern 数据类型 全局变量名
格式2(修饰函数):extern 返回值类型 函数名(数据类型 参数1,数据类型 参数2,…)
使用
在fun.c中定义全局变量和函数,在main.c中调用fun.c中定义的全局变量和函数
fun.c
#include <stdio.h>
void fun1(){
printf("fun.c 的 fun1函数\n");
}
int global = 2024;
main.c
#include<stdio.h>
//use extern
extern int global;
extern void fun1();
int main(){
fun1();
printf("global = %d \n",global);
}
编译执行
注意:extern 所声明的函数所在的文件要一起编译,否则会报错
root@wangjudealy:/learn/day05# gcc main.c fun.c
root@wangjudealy:/learn/day05# ./a.out
fun.c 的 fun1函数
global = 2024
多文件编程框架
头文件(.h 文件)
- 防止其他头文件重复定义宏(条件编译)
- 包含函数声明
- 宏定义
- 需要使用的头文件
- 结构体或枚举类型的声明
- 全局变量的声明
,h文件格式
#ifndef __HEAD_H__
#define __HEAD_H__
语句....
# endif
功能文件(.c 文件)
存放用户所需要的逻辑代码函数,即API,不包含主函数main()
C语言高级
结构体
声明
struct 结构体名{
类型 变量名1;
类型 变量名2;
......
......
......
}
结构体变量的定义
1、先声明,再定义
struct 结构体名 变量名;
2、声明时定义
struct 结构体名{
类型 变量名1;
类型 变量名2;
......
......
......
}变量名列表;
3、不适用类型名,直接定义
struct {
类型 变量名1;
类型 变量名2;
......
......
......
}变量名列表;
typedef的使用
typedef :给已经存在的类型取一个别名
typedef struct 结构体名{
类型 变量名1;
类型 变量名2;
......
......
......
}A; //将 struct 结构体名 定义了一个新的类型名 ‘struct 结构体名 a’ == ‘A a’
访问结构体内部成员变量
- 普通成员变量通过 '.'来访问
- 指针成员变量通过‘->’来访问(注意:结构体中成员为数组时,若要访问,数组名为地址)
- 一般在 .h 文件中,或定义为全局变量
结构体大小计算
结构体变量大小比实际的大,因为存在字节对齐现象
联合体
联合体所有成员共享同一块内存。共用最大的一块内存
比如有两个成员,一个是char,一个是int,则这两个成员共用int类型成员的空间
声明
union name {
类型 成员1;
类型 成员2;
...
...
};
定义和访问成员变量
参考结构体
作用
1、可以使用联合体判断计算机是大端存储还是小端存储
2、可以节省内存空间,比如用户登录,先共用体可以先存用户名,再存密码
枚举类型
声明
enum name{
常量名1;
常量名2;
常量名3;
....
....
....
}
- 枚举元素都是常量
- 枚举元素没有赋值,第一个元素默认为0,以后元素递增
位域
简介
有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用0和1表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种数据结构,叫做“位域”或“位段”。位域将一个字节的二进位划分为几个不同的区域。并说明每个区域的位数,每个域有一个域名,可以按域名操作域。
声明
struct 位域结构名{
类型说明字符1 位域名1:位域长度1; //最低位
类型说明字符2 位域名2:位域长度2; //次低位
.....
类型说明字符n 位域名n:位域长度n;
}
位域位数小于对应类型的位数
一个字节不够时,位域可以存放在下一个字节中,比容剩下两位,要定义6位的位域,可以定义一个2位的空域(无名位于),使下一个位域存放在下一个字节中
相邻位域字段类型相同,且位长之和小于类型总长,则它们相邻存储
相邻位域字段类型不同,根据编译器的差异有些会压缩
位域定义时可以穿插非位域成员
位域成员往往不占用一个完整的字节,有时处于不同的字节开头位置,因此使用&获取位域成员地址是无意义的
struct s2{
unsigned int n1:1;
unsigned int n2:1;
}s_2;
int main(){
struct s2 * p=&s_2;
p->n1=0; //这是允许的
&s_2.n1 ; //这种操作无意义,且不允许
}
定义
参考结构体
代码示例
#include<stdio.h>
struct s1{
unsigned int n1;
unsigned int n2;
}s_1;
struct s2{
unsigned int n1:1;
unsigned int n2:1;
}s_2;
int main(){
printf("结构体==》sizeof(s1)=%d\n",sizeof(s_1));
printf("位 域==》sizeof(s2)=%d\n",sizeof(s_2));
return 0;
}
root@wangjudealy:/learn/day05# ./a.out
结构体==》sizeof(s1)=8
位 域==》sizeof(s2)=4