赞
踩
可以先看几个 shell 编程找找感觉 , 哈哈
#!/bin/bash
sum=0
f1=0
f2=1
#-e 开启echo的转义功能,尾部加\c表示不换行
echo -e "$f1+$f2\c"
#使用expr执行加法
sum=`expr $sum + $f1 + $f2`
#shell脚本中的for循环
for i in $(seq 3 10)
do
f3=`expr $f1 + $f2`
sum=`expr $sum + $f3`
f1=$f2
f2=$f3
echo -e "+$f3\c"
done
echo -e "=$sum"
#!/bin/bash
reverseNum(){
array_len=$# #测试集个数
for num in $*
do
#请在此处键入您的代码
x=$num
#ans=""
while [ $x -gt 0 ]
do
t=$[$x%10]
echo -e "$t\c"
#ans=$[$ans$t]
x=$[$x/10]
done
echo ""
done
}
#!/bin/bash
#请在此处键入你的代码
# 创建 userdata 目录
if [ -d /home/userdata ]
then
chmod 754 /home/userdata
else
mkdir -m 754 /home/userdata
fi
i=1
temp=/home/userdata/user
while [ $i -le 5 ]
do
if [ -d $temp$i ]
then
chmod 754 $temp$i
else
mkdir -m 754 $temp$i
fi
i=$[$i+1]
done
#!/bin/bash
read -p "Please input an integer number: " number
echo -e "the result of '\c"
sum=0
for((i=1;i<=number;i++))
do
sum=$[$i+sum]
if [ $i -le 3 ]
then
echo -e "$i+\c"
elif [ $i -eq $number ]
then
echo -e "...$i\c'"
fi
done
echo -e "' is ==> $sum"
[root@hadoop100 ~]$ vim test.c
#include <stido.h>
int mian()
{
printf("Hello world");
return 0;
}
[root@hadoop ~]$ gcc test.c
// `gcc`默认使用`a.out`作为可执行文件的名字;
[root@hadoop ~]$ ./a.out // ./a.out表示运行当前目录下的a.out命令;
c 语言从程序源代码到二进制执行程序需要经历如下四个步骤:
gcc 编译器使用的方法
gcc 命令选项 参数
常用命令选择项如下:
1)-o:指定生成的输出文件名字;
2)-E:仅执行编译预处理;
3)-S:将 C 代码转换成汇编代码
4)-c:仅执行编译和汇编操作,不进行连接操作
5)-I:包含库所在的路径
6)-L:指定库所在的路径
7)-l:指定使用的库(小写)
[root@hadoop ~]$ vim firstExec.c
#include <stdio.h>
int main()
{
printf("Hwllo GCC\n");
return 0;
}
[root@hadoop ~]$ gcc -S first.c
[root@hadoop100 ~]$ ls -l first.s
[root@hadoop100 ~]$ tail firstExec.s
[root@hadoop100 ~]$ gcc firstExec.c -o firstExec
1)相关知识
在实际的软件开发时, 应该遵守一个基本原则:不要重复造轮子。如果某些代码经常要用到,不仅这个项目能使用,而且也能复用到其它项目上,那么就应该把这部分代码从项目中分离出来,将其编译为库文件,供需要的程序调用。
程序库分为两类,分别是静态库和动态库。本关将主要讲解如何生成静态库。
Windows
系统上的静态库是以.lib
为后缀,而Linux
系统上的静态库是以.a
为后缀的特殊的存档。
Linux
系统的标准系统库可在目录 /usr/lib
与 /lib
中找到。比如,在类 Unix
系统中C
语言的数序库一般存储为文件 / usr/lib/libm.a
。该库中函数的原型声明在头文件 /usr/include/math.h
中。
在 Linux
下,我们可以使用 gcc
和 ar
工具制作和使用自己的静态库,具体过程如下:
1. 将源码文件编译成 .o 目标文件;
2. 使用 ar 工具将多个目标打包成 .a 的静态文件;
注意 Linux 系统上默认的静态库名格式为: libxxx.a
,其中 xxx
为生成库的名称。
案例演示1:
编写一个函数 printHello
,其功能为打印 “Hello world" 字符串,将其编译生成名为 Hello
的静态库,可以使用如下命令:
vim printHello.h
vim printHello.c
gcc -c printHello.c -o printHello.o
ar rcs libHello.a printHello.o
vim
编写 printHello.h
(声明 printHello
函数,方便以后被其它程序调用)#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif
#include <stdio.h>
void printHello()
{
printf("Hello world\n");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VCSNrSkL-1664612753756)(C:\Users\86152\Pictures\Saved Pictures\生成静态库.png)]
静态库的使用方法只需要在编译程序的时候指明要链接的库名称即可,gcc
中有两个参数是关于链接库时所使用的,分别是:-L
和-l
。
案例演示1:
调用以上案例生成的 printHello
函数,可以使用如下命令:
vim main.c
gcc main.c -o exe -L
./ -lHello./exe
vim
编写main.
#include "printHello.h"
int main()
{
printHello();
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0ch91rg-1664612753759)(C:\Users\86152\Pictures\Saved Pictures\编译生成静态库.png)]
样例代码
vim printHello.h
#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif
vim printHello.c
#include <stdio.h>
void printHello()
{
printf("Hello world\n");
}
gcc -c printHello.c -o printHello.o
ar rcs libHello.a printHello.o
vim main.c
#include "printHello.h"
int main()
{
printHello();
return 0;
}
gcc main.c -o exe -L ./ -lHello
./exe
本关任务是学会生成和使用静态库。
具体编程要求如下:
int Add(int a, int b)
,其功能为计算输入参数a+b
的结果;libAdd.a
,并存放在当前目录下;本关的测试需要用户在右侧的命令行下完成,用户只需将需要完成的命令在右侧命令行下直接操作即可,然后点击评测按钮,平台会自动验证用户是否按照要求去检测结果。
vim Add.h
#include <stdio.h>
int Add(int a, int b);
vim Add.c
#include <stdio.h>
int Add(int a, int b)
{
printf("%d\n", a + b);
}
gcc -c Add.c -o Add.o
ar rcs libAdd.a Add.o
vim main.c
#include "Add.h"
int main()
{
Add(1, 2);
return 0;
}
gcc main.c -o out -L ./ -lAdd
./out
本关任务:学会在Linux
系统上生成C
语言的动态库。
上一关学习了如何生成静态库,本关将继续讲解如何生成动态库。
静态库 | 动态库 | |
---|---|---|
名称 | 命名方式是"libxxx.a",库名前加"lib",后缀用".a","xxx"为静态库名 | 命名方式是"libxxx.so", 库名前加"lib",后缀用".so", "xxx"为动态库名 |
链接时间 | 静态库的代码是在编译过程中被载入程序中 | 动态库在编译的时候并没有被编译进目标代码,而是当你的程序执行到相关函数时才调用该函数库里的相应函数 |
优点 | 在编译后的执行程序不在需要外部的函数库支持,因为所使用的函数都已经被编进去了。 | 动态库的改变并不影响你的程序,所以动态函数库升级比较方便 |
缺点 | 如果所使用的静态库发生更新改变,你的程序必须重新编译 | 因为函数库并没有整合进程序,所以程序的运行环境必须提供相应的库 |
Windows
系统上的 动态库 是以.dll
为后缀,而Linux
系统上的 动态库 是以 .so
为后缀的特殊的存档。
在Linux
下,我们可以使用 gcc
制作和使用动态库,具体制作过程如下:
使用gcc命令加-fPIC参数将源码文件编译成.o目标文件;
使用gcc命令加-shared参数将多个目录文件生成一个动态库文件;
注意 Linux
系统上默认的动态库名格式为:libxxx.so
,其中xxx
为生成库的名称。
案例演示1:
编写一个函数printHello
,其功能为打印"Hello world"字符串,将其编译生成名为Hello
的动态库,可以使用如下命令
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
函数,方便以后被其它程序调用)#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif
vim
编写printHello.c
#include <stdio.h>
void printHello()
{
printf("Hello world\n");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-byIkDgFv-1664612753760)(https://data.educoder.net/api/attachments/212811)] [请在右侧“命令行”里直接体验]
动态库的使用方法与静态库使用方式略有不同,除了使用gcc
中的-L
和-l
参数外,想要调用动态库还需要更新Linux
系统中/etc/ld.so.cache
或者修改LD_LIBRARY_PATH
环境变量,否则在运行程序的时候会报**“No such file or directory”**错误。
案例演示1:
调用以上案例生成的printHello
函数,可以使用如下命令:
vim main.c
gcc main.c -o exe -L ./ -lHello
./exe
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V2g2at1e-1664612753761)(https://data.educoder.net/api/attachments/212806)] [使用vim
编写程序]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SOAhdzrH-1664612753763)(https://data.educoder.net/api/attachments/212812)] [请在右侧“命令行”里直接体验]
此时编译正常,当运行的时候会报**“No such file or directory”**错误。
/etc/ld.so.conf
配置文件,然后加入需要加载的动态库目录。ldconfig
更新/etc/ld.so.cache
案例演示1:
更新/etc/ld.so.cache
,然后运行上一个案例生成的exe
,可以使用如下命令:
sudo vim /etc/ld.so.conf
sudo ldconfig
./exe
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fzJPJ0nq-1664612753764)(https://data.educoder.net/api/attachments/212813)]
[使用vim
向/etc/ld.so.conf
文件添加/home/fzm
路径]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HDBEtbkU-1664612753765)(https://data.educoder.net/api/attachments/212814)] [请在右侧“命令行”里直接体验]
LD_LIBRARY_PATH
环境变量在运行可执行文件前修改LD_LIBRARY_PATH
变量为可执行程序指定需要加载的动态库路径。
案例演示1:
修改LD_LIBRARY_PATH
,然后运行上一个案例生成的exe
,可以使用如下命令:
LD_LIBRARY_PATH=. ./exe
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vbkuzGnE-1664612753766)(https://data.educoder.net/api/attachments/212815)] [请在右侧“命令行”里直接体验]
注意:
LD_LIBRARY_PATH告诉了exe程序现在当前目录下寻找链接的动态库;
当运行环境中同时存在同名的静态库和动态库时,默认优先链接动态库;
vim printHello.h
#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
void printHello();
#endif
vim printHello.c
#include <stdio.h>
{
printf("Hello world\n");
}
gcc -fPIC -c printHello.c -o printHello.o
gcc -shared printHello.o -o libHello.so
ls -l libHello.so
[root@hadoop102 样例演示]# ls -l libHello.so
-rwxr-xr-x. 1 root root 8120 Sep 3 15:16 libHello.so
vim main.c
// 在这里调用的库必须是用双引号好引起来
#include "printHello.h"
int main()
{
printHello();
return 0;
}
gcc main.c -o exe -L ./ -lHello
sudo vim /etc/ld.so.conf
ldconfig
LD_LIBRARY_PATH=. ./exe
./exe
本关任务是学会生成和使用动态库。
具体编程要求如下:
int Sub(int a, int b)
,其功能为计算输入参数a-b
的结果;libSub.so
,并存放在当前目录下;/etc/ld.so.conf
,添加当前目录,并更新/etc/ld.so.cache
;本关的测试需要用户在右侧的命令行下完成,用户只需将需要完成的命令在右侧命令行下直接操作即可,然
vim Sub.h
#ifndef __PRINTHELLO_H__
#define __PRINTHELLO_H__
#include <stdio.h>
int Sub(int a, int b);
#endif
vim Sub.c
#include <stdio.h>
int Sub(int a, int b)
{
return a - b;
}
gcc -fPIC -c Sub.c -o Sub.o
gcc -shared Sub.o -o libSub.so
vim main.c
#include "Sub.h"
int main()
{
printf("%d\n", Sub(2, 1));
return 0;
}
vim /etc/ld.so.conf
ldconfig
gcc main.c -o exe -L ./ -lSub
LD_LIBRARY_PATH=. ./exe
./exe
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。