Linux下C语言开发

时间:2021-08-02 03:58:33

vim

vim的基本使用:

[i]和[esc]进行模式的切换、上[k]下[j]左[h]右[l]、写保存[:wq!]、不写保存[:q!]、前[a]后[i]插、行首[I或0]、行尾[A或$]、向上新建一行[O]向下新建一行[o]、连接下面一行来[J]、上[b]/下个字开头[w]、取消操作[u].

前[X]后[x]删除字符、删除光标所在行[dd]删除光标及以下所在行[ndd]、复制光标当前所在行[yy]、复制当前行及其下n行[nyy]、粘贴[p]、*选择复制[v 之后 移动光标之后 y]

文件第一行[gg]最后一行[G]、第n行[:n回车]、不显示/显示行号[:set unnu/ :set nu]、查找光标单词所在关键字[qd]、查找上/下一个关键字[N]/[n]、查找关键字xxx [/xxx]、将匹配部分xxx全部换成yyy[:%s/xxx/yyy/g]

C语言跳转[]、{}、ifdef/else/endif的另一半[%]

vim配置:~/.vimcr ~/.vim

gcc

GNU编译器套件(GNU Compiler Collection)包括C、C++、Objective-C、Fortran、Java、Ada和Go语言的前端,也包括了这些语言的库(如libstdc++、libgcj等等)。

1.常用选项

-E:只进行预处理,不编译

-S:只编译,不汇编

-c:只编译、汇编,不链接

-g:包含调试信息

-o:输出成指定文件名

-I(大写的i):指定include包含文件的搜索目录

-L:指定链接所需库(动态库或静态库)的所在路径、

-l:指定所需链接库的库名

-ansi:ANSI标准 -std=c99:C99标准 -Werror:不区分错误和警告,遇到任何错误和警告都停止编译 -Wall:开启大部分警告提示 -static:—-static

优化选项

-O0:关闭所有优化选项

-O1:第一级别优化,使用此选项可使可执行文件更小、运行更快,并不会增加太多编译时间,可以简写为-O

-O2:第二级别优化,采用了几乎所有的优化技术,使用此选项会延长编译时间

-O3:第三级别优化,在-O2的基础上增加了产生inline函数、使用寄存器等优化技术

-Os:此选项类似于-O2,作用是优化所占用的空间,但不会进行性能优化,常用于生成最终版本

编译的概念

编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。

编译的完整过程:C源程序-->预编译处理(.c)-->编译、优化程序(.s、.asm)-->汇编程序(.obj、.o、.a、.ko)-->链接程序(.exe、.elf、.axf等)

1.预处理

gcc命令[cpp]:$ gcc -E hello.c -o hello.i

预处理是读取c源程序,对其中的伪指令(以#开头的指令,也就是宏)和特殊符号进行“替代”处理;经过此处理,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,仍然是C文件。但内容有所不同。 伪指令主要包括以下三个方面:(1)宏定义指令,如#define Name TokenString,#undef以及编译器内建的一些宏,如DATE, FILE, LINE, TIME, FUNCTION 等。(2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。(3) 头文件包含指令,如#include “FileName”或者#include等。

2.编译、优化

gcc命令[cc]:$ gcc –S hello.i –o hello.s

编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。

优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化,这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。

对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题

3.汇编

gcc命令[as]: $ gcc –c hello.s –o hello.o

经 汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。

目标文件由段组成。通常一个目标文件中至少有两个段:

代码段(文本段):该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。

数据段:主要存放程序中要用到的各种常量、全局变量、静态的数据。一般数据段都是可读,可写,可执行的。

4.链接

gcc命令[ld]: gcc hello.o –o hello

汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决

的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。

链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体,也就是可执行程序。

根据开发人员指定的库函数的链接方式的不同,链接处理可分为两种:

(1)静态链接 和 (2) 动态链接

对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。

5.Linux可执行文件格式ELF
Linux/Unix的可执行文件以及动态库都是以ELF(Executable Linkage Format)存在的。在Linux下,可以使用readelf命令查看ELF文件,关于加载过程所需要的信息都在ELF文件头里面,可以用使用readefl filename -e来查看EFL文件所有的头。

可执行程序的布局:
Linux下C语言开发**

Makefile

1.mikefile简介

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员。在 Linux(unix )环境下使用GNU 的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile 文件的编写。

所要完成的Makefile 文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile 的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个正确的 Makefile。编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令。整个工程完全自动编译,极大提高了效率。

2.makefile的结构

#表示注释

变量定义

VAR=test 定义变量VAR,强制赋值为test

VAR+=app 在VAR之前定义的值后面再追加app这个值

VAR?=testapp 如果之前VAR没有被定义,则定义并使用testapp;否则使用之前的值

第一条目标为总的目标,

依赖可以是文件(目录)或为其他目标

动作可以是Linux命令,动作的那一行第一个字符必须是以TAB键

target: depend1 depend2 depend3 …

[TAB] action1

[TAB ] action2

target1:

[TAB] action1

[TAB] action2

3.makefile的使用

make 找makefile或Makefile文件执行总的目标

make clean 执行makefile文件中的clean目标

make -C directory 进入到directory文件夹中去执行总的目标

make clean -C direcotry 进入到directory文件夹中去执行clean目标

make -f comm_makefile 通过-f选项指定一个makefile文件

make VAR=value 给Makefile传一个参数VAR,其值为value

4.makefile实例

APPNAME=link

LIB_SRCS=linker.c

LIB_NAME=linker

LIB_PATH=.libs

CFLAGS+=-I${LIB_PATH}

LDFLAGS+=-L${LIB_PATH} -l${LIB_NAME}

all: clean static_lib shared_lib install

gcc ${CFLAGS} main.c -o ${APPNAME}_static ${LDFLAGS} -static

gcc ${CFLAGS} main.c -o ${APPNAME}_shared ${LDFLAGS}

@rm -f *.o

static_lib: linker.c

gcc -c ${LIB_SRCS}

ar -rcs lib${LIB_NAME}.a *.o

rm -f *.o

shared_lib:

@gcc -fPIC -shared ${LIB_SRCS}  -o lib${LIB_NAME}.so

clean:

@rm -f *.o

distclean:

rm -rf .libs

rm -rf ${APPNAME}_*

install:

mkdir -p ${LIB_PATH}

mv lib${LIB_NAME}.* ${LIB_PATH}

cp linker.h ${LIB_PATH}

$ ls

linker.c  linker.h  main.c  makefile

$ make

$ make install

$ make clean

$ make distclean