高级Linux程序设计第一章:入门
1、用GCC编译
1.1、创建源文件
-
(main.c) C 源文件 - main.c
#include <stdio.h> #include “reciprocal.hpp” int main (int argc, char **argv) { int i; i = atoi (argv[1]); printf (“The reciprocal of %d is %g\n”, i, reciprocal (i)); return 0; } |
-
(reciprocal.cpp) C++ 源文件 - reciprocal.cpp
#include <cassert> #include “reciprocal.hpp” double reciprocal (int i) { // I should be non-zero. assert (i != 0); return 1.0/i; } |
-
(reciprocal.hpp) 头文件 - reciprocal.hpp
#ifdef __cplusplus extern “C” { #endif extern double reciprocal (int i); #ifdef __cplusplus } #endif |
1.2、编译源文件
-
编译main.c:
% gcc -c main.c |
-
编译reciprocal.cpp:
% g++ -c reciprocal.cpp |
-
参数-I指定搜索头文件的位置。
-
默认情况下,GCC在当前文件夹及标准库的头文件所在的文件夹来搜索头文件。
% g++ -c -I ../include reciprocal.cpp |
-
可以用参数-D在命令行设定宏(macro),并且可以设定宏的值
对于如下程序definemacro.c:
#include "stdio.h" #include "stdlib.h" int main(int argc, char** argv){ int i = 3; #ifdef CHANGEVALUE i = 4; #endif printf("i = %d\n", i); printf("PT = %f\n", PI); } |
如果编译时命令行为gcc definemacro.c,会报‘PI’ undeclared错误。
如果编译时命令行为gcc -D PI=3.14 definemacro.c,则输出如下:
i = 3
PT = 3.140000
如果编译时命令行为gcc -D PI=3.14 -D CHANGEVALUE definemacro.c,则输出如下:
i = 4
PT = 3.140000
-
可以用GCC编译时优化代码.
% g++ -c -O2 reciprocal.cpp |
1.3、链接对象文件
-
g++可以将.o对象文件链接成程序
% g++ -o reciprocal main.o reciprocal.o |
-
如果想链接其他库文件,则用参数-I
例如欲链接库libpam.a,则用如下命令行,编译器会自动加上前缀lib和后缀.a
% g++ -o reciprocal main.o reciprocal.o –lpam |
-
链接器默认在/lib和/usr/lib文件夹下面寻找系统标准库。
-
如果想从其他的文件夹下面寻找要链接的库,则从参数-L指定
% g++ -o reciprocal main.o reciprocal.o -L/usr/local/lib/pam –lpam |
2、用Make自动编译
-
Makefile如下:
reciprocal: main.o reciprocal.o g++ $(CFLAGS) -o reciprocal main.o reciprocal.o main.o: main.c reciprocal.hpp gcc $(CFLAGS) -c main.c reciprocal.o: reciprocal.cpp reciprocal.hpp g++ $(CFLAGS) -c reciprocal.cpp clean: rm -f *.o reciprocal |
-
首先是编译目标(target),紧接着是一个冒号:,然后是完成目标所需的依赖(dependencies)
-
下一行是完成编译目标的规则
-
规则行必须以Tab键开头
-
$(CFLAGS)是make变量,变量可以再Makefile中定义,也可以在命令行定义
% make CFLAGS=-O2 gcc -O2 -c main.c g++ -O2 -c reciprocal.cpp g++ -O2 -o reciprocal main.o reciprocal.o |
3、用GDB调试
3.1、带调试信息编译
-
如果要在编译时带调试信息,则在编译时命令行用-g参数
% make CFLAGS=-g gcc -g -c main.c g++ -g -c reciprocal.cpp g++ -g -o reciprocal main.o reciprocal.o |
3.2、运行GDB
-
启动GDB
% gdb reciprocal |
-
命令run加参数可运行程序
(gdb) run Starting program: reciprocal |
-
命令where可以查看Stack
(gdb) where #0 __strtol_internal (nptr=0x0, endptr=0x0, base=10, group=0) at strtol.c:287 #1 0x40096fb6 in atoi (nptr=0x0) at ../stdlib/stdlib.h:251 #2 0x804863e in main (argc=1, argv=0xbffff5e4) at main.c:8 |
-
用up命令可以弹出运行栈
(gdb) up 2 #2 0x804863e in main (argc=1, argv=0xbffff5e4) at main.c:8 8 i = atoi (argv[1]); |
-
用print命令可以查看变量值
(gdb) print argv[1] $2 = 0x0 |
-
用break命令可以设定断点
(gdb) break main Breakpoint 1 at 0x804862e: file main.c, line 8. |
-
用next命令执行下一条语句
(gdb) next 9 printf (“The reciprocal of %d is %g\n”, i, reciprocal (i)); |
-
用step命令可以进入一个函数
(gdb) step reciprocal (i=7) at reciprocal.cpp:6 6 assert (i != 0); |