Linux环境:C编程基础操作

gcc安装

Ubuntu:

sudo apt-get install gcc

Centos:

sudo yum install gcc

确认是否安装成功

gcc -v

gcc基础编译命令

通过gcc编译命令可以生成后缀名.i的预处理文件,.s的汇编文件,.o的目标文件,.a/.so的库文件和可执行文件
Linux中的C程序源码编译成可执行程序,可能需要依赖多个库文件。可以把这些依赖的库文件当作源码文件的一部分。

常用gcc命令参数
-c 后接编译源文件名
-o 后接产生的目标文件
-g 表示在目标文件中产生调试信息,使得目标文件可以用于 gdb 调试
-D<宏定义> 编译时将宏定义参数传入进去
-Wall 打开所有类型的警告

生成可执行文件的方式

  1. 若干源码文件 直接编译生成可执行文件
    格式:gcc [源码文件名] -o [可执行文件名]
    eg.
    	gcc c1.c c2.c -o test.exe
    
  2. 源码文件生成目标文件,目标文件和依赖的库文件(可以省略)一起链接生成可执行文件
    格式:
    gcc -c [源码文件名] -o [目标文件名]
    gcc -o [可执行文件] [源码文件] -[库文件]
    	gcc -c c1.c -o c1.o
    	gcc -c c2.c -o c2.o
    	gcc -o test.exe c1.o c2.o
    
  3. 源码文件生成预处理文件,预处理文件生成汇编文件,汇编文件生成目标文件,目标文件链接成可执行文件
    	gcc -E  main.c -o main.i
     	gcc -S  main.i -o main.s
      	gcc -c  main.s -o main.o
    	gcc -o  main.exe main.o
    

gcc进阶命令:静态库与动态库文件的生成

  1. 静态库文件生成
    静态库生成较为简单,库文件在链接时直接注入源码文件,生成的可执行文件移植性好,运行时不依赖静态库文件,方便部署,但是不利于升级,每次升级后需要重新生成可执行文件
    生成流程:

    1. gcc编译命令生成目标文件 gcc -c add.c -o add.o
    2. ar命令对目标文件(可以是多个)打包生成库文件 crsv为参数,其中csv是修饰符可以省略 ar crsv libadd.a add.o
    3. 库文件放入默认库文件路径/lib/usr/lib mv libadd.a /lib
    4. 编译生成可执行文件,注意库文件名gcc -o main.exe main.c -ladd

其中,只有第二步需要记忆,其他均为常规操作。

  1. 动态库文件生成
    动态库生成稍微复杂,库文件在链接时不注入源码文件,生成的可执行文件运行时需要依赖动态库文件,移植性差,不便于部署在其他机器,但是升级方便,只需要更新库文件。
    生成流程:

  2. 动态编译生成目标文件 gcc -fPIC -Wall -c add.c

  3. 目标文件生成动态库文件 gcc -shared -o libadd.so add.o

  4. 库文件放入默认库文件路径/lib/usr/lib mv libadd.so /lib

  5. 编译生成可执行文件,注意库文件名gcc -o main.exe main.c -ladd
    需要注意的是第一步和第二步也可以合成一步gcc -fPIC -Wall -shared -o libadd.so add.c

批量编译:Makefile简介

通过编写Makefile文件可以实现批量编译操作

原理:每次编译过程使用的命令大体相同,不同的只有文件名,所以可以使用变量名替换掉文件名,从而实现自动化编译。不同的文件之间存在依赖关系,所以采用自顶(可执行文件)向下(源码文件)的递归过程。
Makefile的语法规则:

  1. 变量命名 :Makefile实际上是采用不同字符串对命令进行替换实现的,所以变量均为字符串格式。为了与命令区别,变量使用时需要加小括号并使用$进行标识$(变量名)

    • 直接赋值定义:变量名:= 字符串
    • 递归式定义 : 变量名 = 字符串(变量名)类似多个指针指向一个地址
  2. 函数:

    • 查找函数$(wildcard *.c),wildcard是函数名,后跟一个参数,作用是将符合该参数规则的文件名当作一列字符串输出,各个文件名之间会隔开。*.c会找到当前目录下的所有.c文件名并输出
    • 字符串替换函数$(patsubst 匹配规则1,匹配规则2,源字符串列表)将源字符串列表中符合匹配规则1的字符串 进行替换 使其符合匹配规则2。Makefile中的通配符为%

    示例OC=$(patsubst %.c,%.o,$(wildcard *.*))含义是将当前目录下所有有后缀名的文件中的.c文件名拿出来,并把.c替换成.o,然后将这一串字符串赋值给变量OC

  3. 规则
    主要用到 :

    • $@代表当前规则下的目标文件\
    • $^代表当前规则的所有依赖文件
    • 所有的.o文件会自动依赖同名的.c文件
    • 一系列的预定义变量
      通过上述规则,即可编写通用的makefile文件,针对特殊需求只需要修改对应变量即可

以下为简单的通用Makefile文件示例

生成可执行文件的Makefile文件

   EXE:=test.exe                                                                                                                                                                              
   #编译后得到的可执行文件的名字
   
   CC:=gcc
   #选择的C编译器 可以根据需要改动
   
   CFLAGS:=-Wall -g
   #gcc编译参数 显示所有警告信息 可调试 可以根据需要改动
   
  LIBSO:=
  #库依赖文件 可以根据需要添加
  
  OC := $(patsubst %.c, %.o, $(wildcard *.c))
  #目标文件列表 用来生成可执行文件
  
  $(EXE):$(OC)
      $(CC) $(CFLAGS) -o $@ $^
  
  .PHONY : clean rebuild
  clean:
      rm -f $(EXE) $(OC)
  rebuild:
      clean $(EXE)

生成静态库文件的Makefile文件

# 库文件名, lib*.a
TARGET  := libtest.a

# 编译器选择
CC      := gcc

#打包程序选择
AR      = ar

#gcc编译参数 显示所有警告信息 可调试 可以根据需要改动
CFLAGS:=-Wall -g

#依赖的库文件
LIBS    :=

# 自动查找当前目录所有 .c 文件,并将目标定义为同名 .o 文件

SOURCE  := $(wildcard *.c)

OBJS    := $(patsubst %.c,%.o,$(SOURCE))

 
$(TARGET) : $(OBJS) 

#生成静态库文件
    $(AR) crvs $(TARGET) $(OBJS)

#移动到/lib中
    mv $(TARGET) /lib

.PHONY : clean delete rebuild

clean :
#删除中间文件
    rm -rf *.o
#删除库文件
delete:
	rm  /lib/$(TARGET)
#重新生成库文件
rebuild:
	clean $(TARGET)


生成动态库文件的Makefile文件

# 库文件名, lib*.so
TARGET  := libtest.so

# 编译器选择
CC      := gcc

#gcc生成动态库文件的编译参数
CFLAGS:= -g -Wall -fPIC -shared -o

#依赖的库文件
LIBS    :=

# 自动查找当前目录所有 .c 文件

SOURCE  := $(wildcard *.c)

$(TARGET) : $(OBJS) 
	$(TARGET) $(CFLAGS) $(TARFET) $(SOURCE) 

#移动到/lib中
    mv $(TARGET) /lib

.PHONY : clean delete rebuild

clean :
#删除中间文件
    rm -rf *.o
#删除库文件
delete:
	rm  /lib/$(TARGET)
#重新生成库文件
rebuild:
	clean $(TARGET)

gcc调试命令gdb

如果在gcc编译程序时加入了-g参数,则可以使用gdb命令对可执行文件进行调试
gdb -q 可执行文件名
#-q参数可以消除gdb启动时输出的无用的版本信息等
常用gdb命令:
l:查看代码
b : 打断点
info b:查看所有断点
tb :打临时断点
r :运行
bt:查看函数堆栈调用信息
delete:删除断点
n:下一步,遇到函数直接执行不进入
s:下一步,遇到函数进入
disable:使某个断点失效
enble:启用某个断点
c:继续运行
p:打印命令,可以用来打印变量
q:退出

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章