Linux之C编程入门

目录

第1关:第一个C程序

任务描述

相关知识

编译C程序

编程要求

答案及其步骤:

第2关:Linux编译C程序

任务描述

相关知识

gcc编译器使用方法

编程要求

答案及其步骤:

第3关:Linux之静态库编写

任务描述

相关知识

生成静态库

使用静态库

编程要求

答案及其步骤:

第4关:Linux之动态库编写

任务描述

相关知识

生成动态库

使用动态库

更新/etc/ld.so.cache来运行动态库

修改LD_LIBRARY_PATH环境变量

编程要求

答案及其步骤:


第1关:第一个C程序

任务描述

本关任务:在Linux系统上编写第一个C语言程序Hello world

相关知识

C语言是Linux操作系统中最常用的编程语言,部分原因在于Linux操作系统本身几乎是采用C语言编写的。使用C语言,程序员可以通过函数库和系统调用非常容易地访问系统服务。另外,还有很多有用的工具为程序开发和维护提供了便利。

本实训将讲解如何编译和链接C语言程序,假设用户掌握了C语言的基本语法。在Windows系统上我们编写C语言程序,我们只需在IDE(windows常使用的IDEvisual studio系列)中写入代码,然后点击编译,如果程序没有语法错误则会生成可执行文件,然后点击运行即可运行生成的可执行文件。其实IDE帮助我们自动的编译和运行程序,所以我们不需要关注程序是如何被编译的,而在Linux系统上我们通常要学会如何使用命令来编译程序,此时,我们需要手动的去编译程序,然后手动的运行程序。

编译C程序

Linux系统上常用的C编译器是gcc,大多数开发板都包含了这个工具。

gcc是开源领域应用最广泛的编译器之一,其具有功能强大,编译代码支持性能优化等特点。而Windows系统上常用的编译器叫cl.exe,该编译器就是Visual Studio集成开发环境所使用的默认编译器。当我们点击编译按钮,Visual Studio则会自动帮我们调用cl.exe编译器去编译我们所写的程序。

使用gcc编译C程序非常简单,可以使用如下命令来编译程序:

gcc 源文件

案例演示1:

使用vim编辑器编写一个"Hello world"C程序,并将源文件保存为test.c,然后编译运行test.c,可以使用如下命令:

vim test.c
gcc test.c
./a.out

使用vim编写如下代码

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

[请在右侧"命令行"里直接体验]

注意

`gcc`默认使用`a.out`作为可执行文件的名字;
./a.out表示运行当前目录下的a.out命令;
编程要求

本关任务是学会使用gcc编译C程序。

具体编程要求如下:

在当前目录下编写一个简单的C程序,输入"Hello world"字符串;

使用gcc编译生成a.out可执行文件;

答案及其步骤:

首先输入如下:

vim test.c    //使用vim编辑器编写,并将源文件保存为test.c

进入编写如下c语言代码:

cpp 复制代码
#include <stdio.h>
int main()
{
    printf("Hello world\n");
}

按i键开始编写

编写完后按Esc键退出编写模式,按Shift键+:键,输入wq保存并退出

cpp 复制代码
gcc test.c    //编译test.c
./a.out    //运行test.c

第2关:Linux编译C程序

任务描述

本关任务:学会gcc编译器的基本使用方法。

相关知识

通过上一关内容学会了如何使用gcc命令来编译C程序,本关将进一步学习gcc编译器。

C语言程序从源代码到二进制行程序需要经历如下四个步骤:

cpp 复制代码
预处理
编译
汇编
链接

[C语言编译流程]

预处理 预处理是根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。

编译 编译是指将预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。

汇编 汇编是指将编译完的汇编代码文件翻译成机器指令,并生成可重定位目标程序的.o文件,该文件为二进制文件,字节编码是机器指令。

链接 链接过程是指链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序,这个可执行程序才是我们最后直接执行的文件。

gcc编译器使用方法

gcc命令具体使用方法如下:

cpp 复制代码
gcc  命令选项 参数

常用命令选项如下:

cpp 复制代码
-o:指定生成的输出文件名字;
-E:仅执行编译预处理;
-S:将C代码转换为汇编代码;
-c:仅执行编译和汇编操作,不进行连接操作;
-I:包含库的头文件路径(大写i);
-L:指定库所在的路径;
-l:指定使用的库(小写l);

案例演示1:

使用vim编辑器编写一个"Hello world"C程序,并将源文件保存为test.c,编译test.c,指定输出可执行文件为test,并运行test,可以使用如下命令:

cpp 复制代码
gcc test.c -o test
./test

使用vim编写如下代码

cpp 复制代码
#include <stdio.h>
int main()
{
    printf("Hello world\n");
    return 0;
}

[请在右侧"命令行"里直接体验]

案例演示2:

仅编译test.c生成汇编语言,可以使用如下命令:

cpp 复制代码
gcc -S test.c

[请在右侧"命令行"里直接体验]

注意 编译生成的汇编文件使用.s为后缀名,汇编生成的二进制文件使用.o为后缀名。

编程要求

本关任务是学会使用gcc编译C程序。

具体编程要求如下:

在当前目录下编写一个简单的C程序,输入"Hello GCC"字符串;

使用gcc编译生成名为firstExec的可执行文件;

答案及其步骤:

首先输入如下:

vim test.c    //使用vim编辑器编写,并将源文件保存为test.c

进入编写如下c语言代码:

cpp 复制代码
#include <stdio.h>
int main()
{
    printf("Hello GCC\n");
}

按i键开始编写

编写完后按Esc键退出编写模式,按Shift键+:键,输入wq保存并退出

cpp 复制代码
gcc test.c -o firstExec    //编译test.c文件,并指定生成的输出出文件的名字
./firstExec    //运行firstExec文件
第3关:Linux之静态库编写
任务描述

本关任务:学会在Linux系统上生成C语言的静态库。

相关知识

在实际的软件开发时, 应该遵守一个基本原则:不要重复造轮子。如果某些代码经常要用到,不仅这个项目能使用,而且也能复用到其它项目上,那么就应该把这部分代码从项目中分离出来,将其编译为库文件,供需要的程序调用。

程序库分为两类,分别是静态库动态库 。本关将主要讲解如何生成静态库

Windows系统上的静态库 是以.lib为后缀,而Linux系统上的静态库 是以.a为后缀的特殊的存档。

Linux系统的标准系统库可在目录/usr/lib/lib中找到。比如,在类Unix系统中C语言的数序库一般存储为文件/usr/lib/libm.a。该库中函数的原型声明在头文件/usr/include/math.h中。

生成静态库

Linux下,我们可以使用gccar工具制作和使用自己的静态库,具体过程如下:

cpp 复制代码
将源码文件编译成.o目标文件;
使用ar工具将多个目标文件打包成.a的静态库文件;

注意 Linux系统上默认的静态库名格式为:libxxx.a,其中xxx为生成库的名称。

案例演示1:

编写一个函数printHello,其功能为打印"Hello world"字符串,将其编译生成名为Hello的静态库,可以使用如下命令:

cpp 复制代码
vim printHello.h
vim printHello.c
gcc -c printHello.c -o printHello.o
ar rcs libHello.a printHello.o

使用vim编写printHello.h(声明printHello函数,方便以后被其它程序调用)

cpp 复制代码
#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif

使用vim编写printHello.c

cpp 复制代码
#include <stdio.h>

void printHello()
{
    printf("Hello world\n");
}

[请在右侧"命令行"里直接体验]

使用静态库

静态库 的使用方法只需要在编译程序的时候指明要链接的库名称即可,gcc中有两个参数是关于链接库时所使用的,分别是:-L-l

cpp 复制代码
-L:用于告诉gcc要链接的库所在目录;
-l:用于指明链接的库名称(小写l);

案例演示1:

调用以上案例生成的printHello函数,可以使用如下命令:

cpp 复制代码
vim main.c
gcc main.c -o exe -L ./ -lHello
./exe

使用vim编写main.c

cpp 复制代码
#include "printHello.h"
int main()
{
    printHello();
    return 0;
}

[请在右侧"命令行"里直接体验]

编程要求

本关任务是学会生成和使用静态库。

具体编程要求如下:

在当前目录下编写一个简单的函数int Add(int a, int b),其功能为计算输入参数a+b的结果;

将Add函数编译生成一个静态库libAdd.a,并存放在当前目录下;

答案及其步骤:
cpp 复制代码
vim Add.h    

进入如下输入:

cpp 复制代码
#include<stdio.h>
int Add(int a,int b);
cpp 复制代码
vim Add.c

进入如下输入:

cpp 复制代码
#include<stdio.h>
int Add(int a,int b)
{
    return a+b;
}
cpp 复制代码
gcc -c Add.c -o Add.o
ar rcs libAdd.a Add.o
vim main.c

进入如下输入:

cpp 复制代码
#include "Add.h"
int main()
{
    int c=Add(1,1);
    return c;
}
cpp 复制代码
gcc main.c -o exe -L ./ -lAdd
./exe

全部输入如下:

第4关:Linux之动态库编写

任务描述

本关任务:学会在Linux系统上生成C语言的动态库。

相关知识

上一关学习了如何生成静态库 ,本关将继续讲解如何生成动态库

静态库动态库的区别:

| 静态库 | 动态库 |
|------|----------------------------------------------|---------------------------------------------------|
| 名称 | 命名方式是"libxxx.a",库名前加"lib",后缀用".a","xxx"为静态库名 | 命名方式是"libxxx.so", 库名前加"lib",后缀用".so", "xxx"为动态库名 |
| 链接时间 | 静态库的代码是在编译过程中被载入程序中 | 动态库在编译的时候并没有被编译进目标代码,而是当你的程序执行到相关函数时才调用该函数库里的相应函数 |
| 优点 | 在编译后的执行程序不在需要外部的函数库支持,因为所使用的函数都已经被编进去了。 | 动态库的改变并不影响你的程序,所以动态函数库升级比较方便 |
| 缺点 | 如果所使用的静态库发生更新改变,你的程序必须重新编译 | 因为函数库并没有整合进程序,所以程序的运行环境必须提供相应的库 |

Windows系统上的动态库 是以.dll为后缀,而Linux系统上的动态库 是以.so为后缀的特殊的存档。

生成动态库

Linux下,我们可以使用gcc制作和使用动态库,具体制作过程如下:

cpp 复制代码
使用gcc命令加-fPIC参数将源码文件编译成.o目标文件;
使用gcc命令加-shared参数将多个目录文件生成一个动态库文件;

注意 Linux系统上默认的动态库名格式为:libxxx.so,其中xxx为生成库的名称。

案例演示1:

编写一个函数printHello,其功能为打印"Hello world"字符串,将其编译生成名为Hello的动态库,可以使用如下命令:

cpp 复制代码
vim printHello.h
vim printHello.c
gcc -fPIC -c printHello.c -o printHello.o
gcc -shared  printHello.o -o libHello.so

使用vim编写printHello.h(申明printHello函数,方便以后被其它程序调用)

cpp 复制代码
#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif

使用vim编写printHello.c

cpp 复制代码
#include <stdio.h>
void printHello()
{
    printf("Hello world\n");
}

[请在右侧"命令行"里直接体验]

使用动态库

动态库 的使用方法与静态库 使用方式略有不同,除了使用gcc中的-L-l参数外,想要调用动态库还需要更新Linux系统中/etc/ld.so.cache或者修改LD_LIBRARY_PATH环境变量,否则在运行程序的时候会报**"No such file or directory"**错误。

案例演示1:

调用以上案例生成的printHello函数,可以使用如下命令:

cpp 复制代码
vim main.c
gcc main.c -o exe -L ./ -lHello
./exe

[使用vim编写程序]

[请在右侧"命令行"里直接体验]

此时编译正常,当运行的时候会报**"No such file or directory"**错误。

更新/etc/ld.so.cache来运行动态库
cpp 复制代码
编辑/etc/ld.so.conf配置文件,然后加入需要加载的动态库目录。
运行ldconfig更新/etc/ld.so.cache

案例演示1:

更新/etc/ld.so.cache,然后运行上一个案例生成的exe,可以使用如下命令:

cpp 复制代码
sudo vim /etc/ld.so.conf
sudo ldconfig
./exe

[使用vim/etc/ld.so.conf文件添加/home/fzm路径]

[请在右侧"命令行"里直接体验]

修改LD_LIBRARY_PATH环境变量

在运行可执行文件前修改LD_LIBRARY_PATH变量为可执行程序指定需要加载的动态库路径。

案例演示1:

修改LD_LIBRARY_PATH,然后运行上一个案例生成的exe,可以使用如下命令:

cpp 复制代码
LD_LIBRARY_PATH=.  ./exe

[请在右侧"命令行"里直接体验]

注意

cpp 复制代码
LD_LIBRARY_PATH告诉了exe程序现在当前目录下寻找链接的动态库;
当运行环境中同时存在同名的静态库和动态库时,默认优先链接动态库;
编程要求

本关任务是学会生成和使用动态库。

具体编程要求如下:

在当前目录下编写一个简单的函数int Sub(int a, int b),其功能为计算输入参数a-b的结果;

将Sub函数编译生成一个动态库libSub.so,并存放在当前目录下;

修改/etc/ld.so.conf,添加当前目录,并更新/etc/ld.so.cache

答案及其步骤:
cpp 复制代码
vim Sub.h

进入如下输入:

cpp 复制代码
#include<stdio.h>
int Sub(int a,int b);
cpp 复制代码
vim Sub.c

进入如下输入:

cpp 复制代码
#include<stdio.h>
int Sub(int a,int b)
{
    return a-b;
}
cpp 复制代码
gcc -fPIC -c Sub.c -o Sub.o
gcc -shared Sub.o -o libSub.so
vim main.c

进入如下输入:

cpp 复制代码
#include "Sub.h"
int main()
{
    int c=Sub(1,1);
    return c;
}
cpp 复制代码
gcc main.c -o exe -L ./ -lSub
vim /etc/ld.so.conf

进入如下输入:

cpp 复制代码
/root    //输入/root
cpp 复制代码
ldconfig
./exe

全部输入如下:

相关推荐
成都古河云22 分钟前
智慧场馆:安全、节能与智能化管理的未来
大数据·运维·人工智能·安全·智慧城市
算法与编程之美24 分钟前
文件的写入与读取
linux·运维·服务器
希言JY41 分钟前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
xianwu54342 分钟前
反向代理模块
linux·开发语言·网络·git
午言若43 分钟前
C语言比较两个字符串是否相同
c语言
Amelio_Ming1 小时前
Permissions 0755 for ‘/etc/ssh/ssh_host_rsa_key‘ are too open.问题解决
linux·运维·ssh
心灵彼岸-诗和远方1 小时前
Devops业务价值流:软件研发最佳实践
运维·产品经理·devops
JuiceFS1 小时前
好未来:多云环境下基于 JuiceFS 建设低运维模型仓库
运维·云原生
Ven%2 小时前
centos查看硬盘资源使用情况命令大全
linux·运维·centos
萨格拉斯救世主2 小时前
戴尔R930服务器增加 Intel X710-DA2双万兆光口含模块
运维·服务器