参考:麦子学院-嵌入式C语言高级
前导课程:掌握简单C语言的基本语法
计算机程序语言的学习思路?
基本程序设计思想+语言工具的特性
基本程序设计思想:
数据类型、运算符、条件分支、循环设计
面向对象的设计
C语言工具的特性:
比如操作底层,尤其是内存地址的寻址及操作,指针的使用
掌掘C语言的设计思路,比普通的语法要重要的多
万变不离其宗,掌掘C语言的核心规律。
不是教程,是一种嵌入式C语言思想和设计的交流
什么时候用?
怎么用?
为什么要这样设计?
C语言深度解剖(第2版》 解开程序员面试笔试的秘密
C专家编程
程序员面试宝典《第4版)
C和指针
嵌入式课程的特点
掌握C语言如何变成机器指令的过程
gcc工具的几个常用选项的意义
【难点】
C编译过程中在gcc工具上的体现
【实验考核】
自己编写程序,利用gcc工具集验证每一步的执行效果
举例说明gcc选项的意义:
gcc -I gcc -L
gcc -E gcc -S gcc -c
c语言的编译过程
可参考:https://mp.csdn.net/mp_blog/creation/success/130063131
c语言常见错误举例
include “name” 当前目录
include 系统库(环境变量)
示例
从abc1.h中引入字符char_c
#include
#include "abc1.h"
int main()
{
char c=char_c;
printf("c(char)=%c,c(int)=%d,c_change(char)=%c,c_change(int)=%d,c_change(HEX)=%#x\n",c,c,c+32,c+32,c+0x20);
return 0;
}
输出:
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
2.c:2:18: fatal error: abc1.h: No such file or directory
compilation terminated.
显然无此文件(文件名错误),改为include “abc.h”,运行正常。
而一般地,将头文件一般放在inc目录下。
建立inc,并把abc.h移入inc:
1、方法1:修改inclue为#include “./inc/abc.h”;
2、方法2:gcc -I ./inc 2.c -o 2
语法错误,
寻找标签是否实现了,链接时是否加入一起链接
示例
#include
#include "abc.h"
void fun(void);
int main()
{
char c=char_c;
printf("c(char)=%c,c(int)=%d,c_change(char)=%c,c_change(int)=%d,c_change(HEX)=%#x\n",c,c,c+32,c+32,c+0x20);
fun();
return 0;
}
main函数中引用了一个fun函数,但没有fun函数的实现,故链接器collect2.exe时出错,
提示:
E:\temp>gcc -I ./inc 2.c -o 2 && "e:\temp"2
C:\Users\Vera\AppData\Local\Temp\ccRNGpif.o:2.c:(.text+0x4b): undefined reference to `fun’
collect2.exe: error: ld returned 1 exit status
解决方法1:不声明,删除fun()的定义并直接实现一个空函数:
void fun(void)
{
}
方法2:2.c不变,新建立abc.c存放fun()的函数实现,如:
abc.c
void fun(void)
{
}
执行程序:>gcc -I ./inc -o 2 2.c abc.c #将所有用到的原材料放在输出文件之后
方法3:分别编译再拼接
E:\temp>gcc -c -I./inc -o a.o 2.c
E:\temp>gcc -c -o b.o abc.c
分别编译完成后的文件都输出在当前目录下:
gcc -o 2 a.o b.o
解决思路:多次实现了标签,只保留一个标签实现
在2个文件中都实现fun()函数,并重新编译,链接:
E:\temp>gcc -c -I./inc -o a.o 2.c
E:\temp>gcc -c -o b.o abc.c
E:\temp>gcc -c -I./inc -o a.o 2.c
E:\temp>gcc -o 2 a.o b.o
提示错误:
E:\temp>gcc -o 2 a.o b.o
b.o:abc.c:(.text+0x0): multiple definition of `fun’
a.o:2.c:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
#include 包含头文件,并在当前位置展开
#deine 宏(替换),不进行语法检查,编译时才检查
#define 宏名 宏体 加括号
#define ABC (5+3)
#define ABC(x) (5+(x)) //宏函数
(C语言编译器或gcc定义)
前后2个下划线
FUNCTIO
LINE
FILE
#include
int main()
{
//本行执行的函数名,所在文件名,本行的行号
printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);
return 0;
}
输出:
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
the main,2.c,7
改示例为
#include
int fun()
{
int a;
//本行执行的函数名,所在文件名,本行的行号
printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);
return 0;
}
int main()
{
fun();
return 0;
}
输出(实际调用的函数名称和所在行号):
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
the fun,2.c,8
#ifdef #else #endif
调试版本
发行版本
示例
原始代码:
#include
int main()
{
printf("=========================\n",__FILE__);
printf("hello world!\n");
return 0;
}
debug期间允许__FILE__行显示,但发行版本中不显示,怎么实现:
#include
int main()
{
#ifdef ABC
printf("=========================\n",__FILE__);
#endif
printf("hello world!\n");
return 0;
}
未定义ABC时,不打印:
E:\temp>cd “e:\temp” && gcc 003.c -o 003 && "e:\temp"003
hello world!
需要显示调试信息时,只要在#ifdef ABC之前定义ABC即可。
但是该方法还是要修改源文件,不是很方便,故引入gcc -D:cpp之前增加define
如:gcc -DABC -o build 003.c 相当于编译前引入: #define ABC。