linux C 编程入门

从Hello World开始

vim编辑器前边已经介绍过,这里学习一下gcc编译器

gcc [选项] [文件名字]

-c: 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o: <输出文件名>用来指定编译结束以后的输出文件名,如果使用这个选项的话 GCC 默认编译出来的可执行文件名字为 a.out。
-g: 添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编译的时候生成调试所需的符号信息。
-O: 对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进行优化,这样产生的可执行文件执行效率就高。
-O2: 比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。

编写代码

使用vim编辑器编写(.c)源代码,在那之前先进行一下vim设置,修改/etc/vim/vimrc文件,文件末尾添加命令,方便C编程。

sudo vi /etc/vim/vimrc

添加内容:
set ts=4	//设置tab制表符为4
set nu		//设置行标号

//set noexpandtab

编辑main.c文件,输出hello world!。

编译代码

使用GCC 编译器编译源代码(.c)并链接生为可执行文件(.out)
不同的架构需要不同的gcc编译器,x86架构和arm架构就不同。

gcc main.c -o main	//编译+链接生成可执行文件
./main				//运行程序

gcc -c main.c		//编译
gcc main.o -o main	//链接
./main				//运行程序

编译流程

GCC 编译器的编译流程是:预处理、编译、汇编和链接。

//源代码(.c)生成目标代码(.o)
预处理就是展开所有的头文件、替换程序中的宏、解析条件编译并添加到文件中。
编译是将经过预编译处理的代码编译成汇编代码,也就是我们常说的程序编译。
汇编就是将汇编语言文件编译成二进制目标文件。

//目标代码(.o)和库代码、启动代码链接成可执行文件(.out)
链接就是将汇编出来的多个二进制目标文件链接在一起,形成最终的可执行文件,链接的时候还会涉及到静态库和动态库等问题。

Makefile的使用

Makefile是一个文件,就是控制gcc编译器**去编译、链接数量较多的源文件。**大大节约了开发时间。

1.首先在工程目录下创建Makefile文件。
2.Makefile文件中格式

目标文件: 依赖文件集合
	命令 1
	命令 2
	……
	
//命令列表中的每条命令必须以 TAB 键开始,不能使用空格!
//命令即为shell命令

3.使用make命令,make 命令会在当前目录下查找以Makefile(makefile 其实也可以)命名的文件。
4.当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标。

Makefile 规则格式

除了 Makefile 的“终极目标”所在的规则以外,其它规则的顺序在 Makefile 中是没有意义的,“终极目标”就是指在使用 make 命令的时候没有指定具体的目标时, make 默认的那个目标,它是 Makefile 文件中第一个规则的目标,如果 Makefile 中的第一个规则有多个目标,那么这些目标中的第一个目标就是 make 的“终极目标”。

和python一样 # 为注释

例如:

#Makefile文件内容main为终极目标
1 main: main.o input.o calcu.o
2 	gcc -o main main.o input.o calcu.o
3 main.o: main.c
4 	gcc -c main.c
5 input.o: input.c
6 	gcc -c input.c
7 calcu.o: calcu.c
8 	gcc -c calcu.c
9
10 clean:
11 	rm *.o
12 	rm main
#命令操作
make		#生成可执行文件
make clean	#清除指定文件

Makefile 变量

问题:如果需要重复的输入文件名会很浪费时间也不容易修改。
解决:Makefile 也支持字符串变量

1、赋值符“=”

1 name = zzk			#zzk赋值给变量name
2 curname = $(name)		#$(name)取值
3 name = zuozhongkai	#修改变量内容
4 
5 print:
6 	@echo curname: $(curname)#打印字符

make print
zuozhongkai

“#”作为注释标志,“$”(变量)取字符,
print: @echo 字符串 打印内容,@表示make命令不会打印。

2、赋值符“:=”

1 name = zzk			#zzk赋值给变量name
2 curname := $(name)		#$(name)取值
3 name = zuozhongkai	#修改变量内容
4 
5 print:
6 	@echo curname: $(curname)#打印字符

make print
zzk

“:=”和“=”的区别就是,“:=”给变量赋值后,该变量得到的字符串就确定了。

curname ?= zuozhongkai

如果变量 curname 前面没有被赋值,那么此变量是“zuozhongkai”
curname:“我没有值,我要你的”

如果前面已经赋过值了,那么就使用前面赋的值。
curname:“我已经有值了,不需要了”

4、变量追加“+=”

objects = main.o inpiut.o
objects += calcu.o

objects 变成了“main.o input.o calcu.o”

5、sinclude 和 include
在 Makefile 中都是读取指定文件内容,这里读取文件 ( s r c t r e e ) / a r c h / (srctree)/arch/ (srctree)/arch/(ARCH)/config.mk 的内容。 sinclude 读取的文件如果不存在的话不会报错。

6、变量使用规则

$(CONFIG_SYS_ARCH:"%"=%) // 也就是提取CONFIG_SYS_ARCH 里面双引号“”之间的内容。

比如 :CONFIG_SYS_ARCH=“arm”的话,ARCH=arm。


## Makefile 自动化变量
**自动化变量**就是这种变量会把模式中**所定义的一系列的文件**自动的挨个取出,直至**所有的符合模式的文件**都取完。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020072611371227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxNzUzMDUy,size_16,color_FFFFFF,t_70)

```bash
1 objects = main.o input.o calcu.o
2 main: $(objects)
3 	gcc -o main $(objects)
4 
5 %.o : %.c		#目标文件.o 依赖文件.c
6 	gcc -c $<	#所有.c编译成.o
7 
8 clean:
9 	rm *.o
10 	rm main

“%”makefile命令类似于通配符,“$<”自动化变量,所有一系列变量。

Makefile 伪目标

伪目标不代表真正的目标名,通过指定这个伪目标来执行其所在规则的定义的命令

#如果目录中有clean文件,则会被认为是目标名
clean:
	rm *.o
	rm main
#这样不怕目录中有clean,明确是伪命令	
.PHONY : clean
	rm *.o
	rm main

Makefile 条件判断

<条件关键字>
	<条件为真时执行的语句>
else
	<条件为假时执行的语句>
endif

条件关键字有 4 个: ifeq、 ifneq、 ifdef 和 ifndef
ifeq 用来判断是否相等, ifneq 就是判断是否不相等

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’ ,‘<参数 2>’
ifeq “<参数 1>” , “<参数 2>#参数即字符

ifdef 用来判断是否相等, ifndef 就是判断是否不相等

ifdef <变量名>
ifndef <变量名>

Makefile 函数使用

Makefile 中的函数是已经定义好的,我们直接使用。

$(函数名 参数集合)
#或者
${函数名 参数集合}
#参数集合之间用“,”隔开

1、函数 subst,用来完成字符串替换

#函数返回被替换以后的字符串
$(subst <from>,<to>,<text>)	//将字符串<text>中的<from>内容替换为<to>

#比如:
$(subst zzk,ZZK,my name is zzk)	//把字符串“my name is zzk”中的“zzk”替换为“ZZK”

2、函数 patsubst,用来完成模式字符串替换

#函数返回被替换以后的字符串
$(patsubst <pattern>,<replacement>,<text>)	//查找字符串<text>中的单词是否符合模式<pattern>,如果匹配就用<replacement>来替换掉

#比如:
$(patsubst %.c,%.o,a.c b.c c.c)	//将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”

3、函数 dir,用来提取目录部分

#返回值是文件名序列<names>的目录部分
$(dir <names…>)	//从文件名序列<names>中提取出目录部分

#比如:
$(dir </src/a.c>)	//提取文件“/src/a.c”的目录部分,也就是“/src”。

4、函数 notdir,去除文件中的目录部分,也就是提取文件名

$(notdir <names…>)

#比如:
$(notdir </src/a.c>)	//提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。

5、函数 foreach,用来完成循环

$(foreach <var>, <list>,<text>)	//把参数<list>中的单词逐一取出来放到参数<var>中,然后再执行<text>所包含的表达式

每次< text >都会返回一个字符串,循环的过程中, < tex t>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,
< text >所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。
6、函数 wildcard
问题:%只能用在规则中,不能用于函数。
解决:这就需要wildcard函数。

$(wildcard PATTERN…)

#比如:
$(wildcard *.c)	//获取当前目录下所有的.c 文件,类似“%”。

linux的学习就先到这,个人觉得主要还是实践练习,在后期学习的时候再做补充。

7、函数origin,返回值就是变量来源

$(origin <variable>)    #variable 是变量名

比如:
$(origin V)	//如果变量 V 是在命令行定义的那么它的来源就是"command line",返回command line。

8、filter 函数,过滤函数

$(filter <pattern...>,<text>)  //以 pattern 模式过滤 text 字符串中的单词,仅保留符合模式 pattern 的单词,
可以有多个模式。函数返回值就是符合 pattern 的字符串。

比如:
$(filter 4.%,$(MAKE_VERSION)) //保留MAKE_VERSION中的4.%的字符

9、函数 firstword,获取首单词

$(firstword <text>)	//取出 text 字符串中的第一个单词,函数的返回值就是获取到的单词。

10、函数shell,执行shell命令

$(shell <command>)	//执行命令行的shell脚本



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值