day11嵌入式(2022.1.17)

2022-12-02 14:33:41 浏览数 (2)

  1. gcc编译器有什么用?

将代码文本编译为机器能识别的二进制指令。

  1. 代码最终得到程序,经过了哪4个步骤?

预处理、编译、汇编、链接

  1. 经过哪个步骤之后,代码不能直接阅读了?

汇编。

  1. 对于代码的语法检查(提示错误行号)属于在哪个步骤进行?

编译。

  1. 为什么代码漏写函数,gcc编译时不提示出现错误的行号?

因为函数链接定位在链接的阶段,而不是在编译阶段。

==================1.gcc编译流程==========================

  1. 预处理:(代码文本 ---> 预处理文本)

指令:gcc hello.c -o hello.i -E

作用:处理所有的预处理指令(以#开头,比如头文件包含、宏定义、条件编译)

  1. 编译:(预处理文本 ---> 汇编文件)

指令:gcc hello.i -o hello.s -S

作用:词法、语法分析,根据平台生成最接近机器的语言(汇编)。

  1. 汇编:(汇编文件 ---> ELF可重定位文件)

指令:gcc hello.s -o hello.o –c

作用:将汇编指令文件翻译为可直接运行的二进制指令流。

  1. 链接:(ELF可重定位文件 库链接 ---> 最终程序)

指令:gcc hello.o -o hello –lc -lgcc

作用:重定位(函数和全局变量等)、链接库、合并段

备注:

  1. 汇编阶段,是处理汇编文件,生成二进制机器指令。
  2. -lXXX表示链接XXX库(-l: library)
  3. 预处理阶段,不会对代码进行语法词法分析。
  4. 链接阶段会对所有函数、全局变量进行重定位、链接,如果此时出现问题,不会提示出错行号。

================== 2.预处理指令 ==========================

在源码中,以#开头的语句,称为预处理指令,他们不属于C语言语法。

  1. 宏定义
代码语言:javascript复制
#define PI 3.1415926    // 预处理阶段中,将代码中所有宏进行替换。
  1. 条件编译(有点类似于分支结构)
代码语言:javascript复制
#if #ifdef #ifndef #elif #else #endif 
  1. 头文件包含
代码语言:javascript复制
#include <stdio.h>

备注:

  1. 宏名一般使用全大写字母,用以区别普通变量、函数。
  2. 带参宏,也称为宏函数,但是不存在函数调用机制。
  3. 宏定义的作用:
  4. 可使代码更具可读性:字符单词一般比纯数字更容易理解含义。
  5. 使得代码更方便修改:只需修改宏定义,即修改了所有该宏定义表达式。
  6. 提高程序运行效率:函数的调用是需要切换时间的,而宏定义是直接展开,不占用运行时间。
  7. gcc编译指令中,可添加 -D选项,往工程中添加指定的宏。

可添加一些调试语句,通过编译指令去控制调试语句的输出。

gcc demo4_条件编译ifdef-ifndef.c -o demo –DTEST

  1. 条件编译属于预处理指令,在预处理阶段就已经完成了判断,程序运行过程中不会再次判断。
  2. 下列语句可避免头文件中的内容重复加入编译:

demo1_编译过程

代码语言:javascript复制
#include <stdio.h>
#include <string.h>

void hahaha(char *str);

int main()
{
	printf("hello world.n");

	hahaha("hello world.n");

	return 0;
}

 demo2_define宏定义

代码语言:javascript复制
#include <stdio.h>
#include <string.h>

// 不带参宏
// #define PI
#define PI 3.1415926	// 预处理阶段中,将代码中所有宏进行替换。

// 带参宏(宏函数)
#define SUM(a,b) (a b)

// 子函数
float func_sum(float a, float b);

int main()
{
	printf("hello world.n");

	float r = 5.0;

	printf("面积: %fn", PI*r*r);
	printf("周长: %fn", 2*PI*r);

	float var1 = 1.2;

	float sum = func_sum(r, var1)*2;
	printf("sum: %fn", sum);
	sum = SUM(r, var1)*2;
	printf("sum: %fn", sum);

	return 0;
}

float func_sum(float a, float b)
{
	return a b;
}

demo3_条件编译_if-else

代码语言:javascript复制
#include <stdio.h>
#include <string.h>

int main()
{
#if 0
	printf("hello world.n");
	printf("hello world.n");
	printf("hello world.n");
	printf("hello world.n");
	printf("hello world.n");
	printf("hello world.n");
#else
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
#endif


	return 0;
}

demo4_条件编译ifdef-ifndef

代码语言:javascript复制
#include <stdio.h>
#include <string.h>

int main()
{
#ifdef TEST
	printf("[%d]n", __LINE__);
#endif

	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");
	printf("nihao 123.n");

#ifdef TEST
	printf("[%d]n", __LINE__);
#endif


	return 0;
}

demo5_使用自己的头文件

代码语言:javascript复制
#include <stdio.h>
#include <string.h>
	// 包含系统头文件

#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
#include "myhead.h"
	// 包含自定义头文件

int main()
{
	printf("%dn", ABC);

	return 0;
}

myhead.h

代码语言:javascript复制
#ifndef _MYHEAD_H
#define _MYHEAD_H

#define ABC 1234

#endif

0 人点赞