20240805嵌入式学习笔记

编译

C语言程序的编写经过四个过程

编辑、编译、运行、调试。从编译环节到到生成可执行文件需要经过四个步骤:

预处理:展开宏和头文件,将注释用空格替代,过滤掉无用的条件编译代码。最终生成一个没有宏定义,没有条件编译指令,没有特殊符号的文件(.i文件)。预处理的指令为:gcc -E main.c -o main.i

编译:编译过程指的是将高级语言(C语言、python等语言)转换为汇编语言文件(.s文件)。

汇编:汇编过程是将汇编文件转换为机器代码文件(.o文件)。

链接:将使用到的文件链接到一起,生成最终可执行文件。

预处理

预处理包含对宏定义、条件包含和条件编译的操作。

宏定义

宏的语法为 "#define 标识符 字符串"。

//宏定义
#define PI 3.14

一般将宏名大写,用以区分常规变量。预处理实质是将字符串以外的宏名用宏值进行原样替换。

#undef:取消宏定义,用于结束宏生命周期,只有在作用域#define和#undef之间的宏名才会被原样替换。

代码示例:

#define PI 3.14
int r = 4;
float s = PI * r * r;
float c = PI * r * 2;
//定义一个宏用来表示圆周率,可以供不同运算使用

带参宏定义

带有参数的宏,实质上依然为原样替换。语法为 ”#define 宏名(参数) 宏值“

//带参宏定义
#define SUM(a,b) a+b

带参宏会在原样替换时会把参数一同替换,带参宏预处理时不会考虑运算优先级,为了防止出现优先级错误,建议在定义时将所有参数用小括号包围。

带参宏又被叫做宏函数,但区别于函数,函数本质是代码的调用,且带参宏不检查语法错误。

代码示例:

#include <stdio.h>
#define ADD(a,b) a+b
#define MINU(a,b) a-b
#define PLUS(a,b) a*b
#define DIV(a,b) a/b

int main(void)
{
	int x,y;
	scanf("%d %d",&x,&y);
	printf("%d + %d = %d\n",x,y,ADD(x,y));
	printf("%d - %d = %d\n",x,y,MINU(x,y));
	printf("%d * %d = %d\n",x,y,PLUS(x,y));
	printf("%d / %d = %d\n",x,y,DIV(x,y));
	return 0;
}

注意:上述宏定义和带参宏的原样替换都发生在预处理阶段,宏经过预处理被字符进行替换,但直到运行时值才会经过运算。且如果不使用续行符宏需要写在一行。

文件包含 

文件包含一般指头文件的包含。有两种形式:

#include <头文件>和#include "头文件"

两种包含方式区别在在于使用”<>“时,预处理阶段会在系统默认路径下查找头文件;使用” "" “时系统会在当前目录下进行查找,如果没有找到再回默认路径下查找。

条件编译

条件编译有三种形式:

#ifdefine 标识符
程序段1
#else
程序段2
#endif

当标识符为真时保留程序段1,为假时保留程序段2。

#ifndef 标识符
程序段1
#else
程序段2
#endif

 当标识符为假时保留程序段1,为真时保留程序段2。

#if 表达式
程序段1
#else
程序段2
#endif

当表达式为真时保留程序段1,为假时保留程序段2。通常简写为#if 0、#endif用于代码调试。

头文件

头文件的编写常规规则:

#ifndef _STDIO_H_
#define _STDIO_H_

---头文件内容---

#endif

在初始位置判断是否已经包含,如果没有包含则定义一个宏,在后续多个文件调用同一个头文件时防重复定义。

指针

指针基础

指针概念:是内存单元的编号,也是地址。是一种专门用来处理地址的数据类型

语法

基类型  *  指针变量名

int *p;    //int *是数据类型;p是变量名;

int a = 10;
int *p = &a;    
//取a的首地址,存放在p中

理解:指针变量中存放目标变量的地址,可以称为指针指向目标变量。 

基类型:几大数据类型。用来表示存放的地址所指向的变量的类型。基类型要与指向空间的数据类型匹配。

*:在定义时表示定义的变量p是指针类型的变量;作为指针运算符时,只能对指针进行运算。表示间接访问指针指向的基类型的内存空间。

将定位到指针中的地址,偏移出基类型大小(sizeof int...)的空间,把偏移出的空间当作一个基类型,把地址指向的变量的数据填入偏移出的空间,实现间接访问。(直接访问:直接对参数的数值进行操作;间接访问:通过获取地址,将值读取后)

代码示例:

在定义时*表示变量为指针类型。在使用时*表示间接访问被指向的空间的数据。

#include <stdio.h>

int sum(int *i,int *j)	//形参接受数据类型为指针
{
	int sum;
	sum = *i + *j;	//计算时间接访问取数值进行运算

	return sum;
}

int plus(int *i,int *j)
{
	int plus = *i * *j;
	return plus;
}


int main(void)
{
	int a,b;
    printf("Input two numbers:\n");
	scanf("%d %d",&a,&b);
	int *i,*j;		//定义指针变量
	i = &a;
	j = &b;		//取地址交给指针变量,间接读取数值
	int sum0 = sum(i,j);		//只传递指针(地址)	
	int plus0 = plus(i,j);
	printf("%d\n",sum0);
	printf("%d\n",plus0);

	return 0;
}

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值