Linux编程基础之GCC编辑器的使用


前言

操作系统:Fedora
本文为学习笔记,通过使用一些常用的命令,完成一些简单的例子,来大概了解GCC编译器的使用


编译运行hello,world

用VI编辑器编辑world.c 文件

vi world.c

在这里插入图片描述

文件内容如下

#include <stdio.h>
int main(){
        printf("hello,world!\n");
        return 0;
}

按Esc键切换至VI编辑器的命令模式,输入 : wq! 将文件保存
在这里插入图片描述

输入下列命令,对world.c 程序进行编译

gcc world.c

然后使用 ls -1 列出当前目录下所有文件,会发现一个名为a.out 的程序,这就是 gcc world.c 命令后得到的可执行文件。
输入以下命令执行该文件

./a.out

可得到 hello,world 的输出结果
在这里插入图片描述


GCC常用选项:预处理控制

GCC可以对C源程序中的预处理器进行处理,主要用法如下

-E 选项

该选项指示GCC编辑器仅对输入文件进行预处理,同时将预处理器的输出送到标准输出即屏幕上而不是文件。例如,执行gcc -E world.c 将预处理后的结果在屏幕上显示出来。
以下是处理结果(不完全显示)
(不完全显示)

-D name 选项

预定义名称为 name 的宏,其内容为1。通过宏的定义和取消,则可以非常方便地控制这些调试信息。如可以通过取消名为HELLO的宏,将所有该宏控制的调试信息取消掉。
编写一个程序 debug.c 内容如下:

#include <stdio.h>
void main(){
  int arr[10],i=0;
  for(i=0;i<10;i++){
    arr[i]=i;
    if(HELLO){  //使用了一个名为HELLO的宏,该宏在编译的时候定义
      printf("arr[%d]=%d\n",i,arr[i]);
    }
  }
}

在编译的时候定义宏HELLO的值,来控制是否显示调试信息,
(在这里,gcc 通过 -DHELLO 参数定义 HELLO 宏且其默认值为1,因此程序得以执行,从而显示调试信息,可以使用 -DHELLO=0 取消宏定义,从而拒绝显示调试信息)例如,使用如下命令编译该程序:

gcc -DHELLO -o debug debug.c

然后使用执行命令 ./debug 命令执行该程序,得到如下结果:
在这里插入图片描述
使用 -DHELLO=0 取消宏定义,从而拒绝显示调试信息

gcc -DHELLO=0 -o debug debug.c

然后重新执行 debug 程序,发现无调试信息显示。此时程序中 HELLO 为0,因此 if 语句不会执行。
在这里插入图片描述


GCC常用选项:编译及警告信息控制选项

(1)-o 选项。该选项指定 gcc 的输出文件名。-o 选项后面必须指定一个文件名。例如,gcc -o hello hello.c 表示将 hello.c 编译成名为 hello 可执行文件。
程序 test.c 内容如下

#include <stdio.h>
#define sum(a,b) a+b //宏定义
void main(){
        int num=sum(1,2);
        printf("num=%d\n",num);
}

执行 gcc -E test.c,可观察对原程序 test.c 的与处理结果,但可通过 -o 命令指定保存预处理结果的文件名称,注意文件要以 .i 结尾(C/C++ 预处理文件的后缀)
在这里插入图片描述
……(中间省略)
在这里插入图片描述
文件中最上面一部分内容是 stdio.h 文件的内容,而 int num=1+2 代码表示 GCC 编译器将宏定义进行了替换。下面通过执行 gcc -S 命令产生 test.c 的汇编文件 test.s
在这里插入图片描述
在这里插入图片描述
上面的代码就是所产生的汇编代码,gcc 中使用 AT&T 语法格式而不是 intel 的汇编语言。
将上面的汇编代码进行汇编,产生目标代码文件。这里使用 -c 选项。该命令产生二进制代码,但该代码并不可直接执行。
用 nm 命令查看目标文件中的符号,用 nm 命令查看 test.o 文件的内容
在这里插入图片描述
该目标文件中有两个符号,分别为 main 和 printf。T 表示该符号再代码中,U 表示符号未定义,所以 printf 函数再当前文件中找不到相关代码,要从外部库中链接进来。
链接命令 gcc -o test test.o 再用 nm 查看 test 文件中的符号。
在这里插入图片描述
……(省略显示)
在这里插入图片描述
可以看出 printf 已经被链接到 glibc2.0 库。
最后执行 test 程序得到 num=3 的结果
在这里插入图片描述


GCC常用选项:GCC链接选项

程序 math1.c 使用了math 函数,而该函数定义在库文件中。

#include <stdio.h>
#include <math.h>
int main(){
        printf("hello world\n");
        double pi=3.1415926;
        printf("sin(pi/2)=%f",sin(pi/2));
        return 0;
}

直接使用 gcc -o math1 math1.c 编译程序,会出现如图所示的错误提示(注:某些发行版本的 Linux 操作系统中可能不会出现该错误,这是因为它会自动链接数学函数库)
该错误提示找不到函数 sin 定义,可通过提供相应数学库解决。用 gcc -o math1 math1.c -lm 命令重新编译,再执行,可得正确结果。(注意:不是1m)
在这里插入图片描述


利用GCC创建库文件

(1)GCC创建静态库文件方法
calc.h 文件内容为两个函数原型,分别计算两数的平均值、两数之和

double aver(double,double);
double sum(double,double);

aver.c 文件实现第一个函数

#include "calc.h"
double aver(double num1,double num2){
        return (num1+num2)/2;
}

sum.c 实现第二个函数

#include "calc.h"
double sum(double num1,double num2){
        return (num1+num2);
}

静态库文件为一系列目标文件组成的单一文件,首先要用 gcc 命令将其编译为目标文件。-c 参数将文件编译为目标文件,而不进行汇编和链接
在这里插入图片描述
使用命令 ar 生成静态库文件:
libmycalc.a 为静态库文件名,必须以 lib 开头,后缀必须为 .a 参数 r 表示将目标文件加入静态库中,如果库中有同名文件,则覆盖。参数 c 表示创建新的静态库文件。
在这里插入图片描述

调用静态库中的 aver 和 sum 函数
程序 main.c 调用了该静态库中的aver 和 sum 函数

#include <stdio.h>
#include "calc.h"
int main(int argc, char* argy[]){
        double v1,v2,m,sum2;
        v1 = 3.2;
        v2 = 8.9;
        m = aver(v1,v2);
        sum2=sum(v1,v2);
        printf("The mean of %3.2f and %3.2f is %3.2f\n",v1,v2,m);
        printf("The sum of %3.2f and %3.2f is %3.2f\n",v1,v2,sum2);
        return 0;
}

使用如下命令编译 main.c 程序

gcc main.c -Bstatic -L. -lmycalc -o static-main

其中:
-Bstatic参数强制 gcc 使用静态库中的函数定义
-L 参数指定库文件的路径(因为上面步骤所生产的库文件与main.c 现在处于同一目录下,因此这里为“.”)
-lmycalc 表示寻找名为libmycalc.a的库文件;
-o 指定输出可执行程序的名称。
执行该程序 ./static-main
在这里插入图片描述
但是我参考的那本书上执行程序用的是

./main

我认为这里书上出错了,参考书如下
在这里插入图片描述
在这里插入图片描述


(2)GCC创建动态库方法
生成目标文件,其中参数 -fPIC 表示生成位置无关代码
在这里插入图片描述将目标文件利用下列命令生成共享库

gcc -fPIC -shared aver.o sum.o -o libmycalc.so
//或 gcc -shared aver.o sum.o -o libmycalc.so

书上的命令为 gcc -shared libmycalc.so aver.o sum.o -o 出错,无法执行
在这里插入图片描述
使用该共享库编译链接 main.c 程序
在这里插入图片描述
可用 ls -l (这里为小写的 L ) 命令,查看shared-main 程序的大小
在这里插入图片描述

在这里插入图片描述
设置环境变量

LD_LIBRAR_PATH=.  #将库文件路径设置为当前路径
export LD_LIBRAR_PATH  #使环境变量LD_LIBRAR_PATH立即生效

执行命令 ./shared-main
在这里插入图片描述
将共享库 libmycalc.so 删除,再执行 ./shared-main 命令,得到如下错误信息
在这里插入图片描述


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huazi-J

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值