当前位置:   article > 正文

头歌——Linux——下的 c 编程_头歌linux之静态库编写

头歌linux之静态库编写

可以先看几个 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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
#!/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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
 #!/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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
#!/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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
[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命令;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

  • 预处理
    • 预处理是根据处理指令组装新的 C / C ++ 程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有新的不同。
  • 编译
    • 编译是指将预处理完的文件进行行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。
  • 汇编
    • 编译是指将处理完的汇编代码文件翻译成机器指令,并生成重定位目标程序的 .o 文件,该文件为二进制文件,字节码是机器指令。
  • 连接
    • 连接过程是指连接机器一个个目标文件(或许还会有库文件)连接在一起生成完整的可执行程序,这个可执行程序才是我们最后直接执行的文件。

gcc 编译器使用的方法

gcc 命令选项 参数

常用命令选择项如下:

1)-o:指定生成的输出文件名字;
2)-E:仅执行编译预处理;
3)-S:将 C 代码转换成汇编代码
4)-c:仅执行编译和汇编操作,不进行连接操作
5)-I:包含库所在的路径
6)-L:指定库所在的路径
7)-l:指定使用的库(小写)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

第3关:Linux 之静态库编写


1)相关知识

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

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

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

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

生成静态库

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

1. 将源码文件编译成 .o 目标文件;

2. 使用 ar 工具将多个目标打包成 .a 的静态文件;

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

案例演示1:

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

  1. vim printHello.h

  2. vim printHello.c

  3. gcc -c printHello.c -o printHello.o

  4. ar rcs libHello.a printHello.o

  • 使用 vim 编写 printHello.h (声明 printHello函数,方便以后被其它程序调用)
  1. #ifndef __PRINTHELLO_H__
  2. #define __PRINTHELLO_H__
  3. #include <stdio.h>
  4. void printHello();
  5. #endif
  • 使用 vim 编写printHello.c
  1. #include <stdio.h>
  2. void printHello()
  3. {
  4. printf("Hello world\n");
  5. }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VCSNrSkL-1664612753756)(C:\Users\86152\Pictures\Saved Pictures\生成静态库.png)]

使用静态库

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

  1. -L:用于告诉gcc要链接的库所在目录;
  2. -l:用于指明链接的库名称(小写l);

案例演示1:

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

  1. vim main.c
  2. gcc main.c -o exe -L
  3. ./ -lHello./exe
  • 使用vim编写main.
  1. #include "printHello.h"
  2. int main()
  3. {
  4. printHello();
  5. return 0;
  6. }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0ch91rg-1664612753759)(C:\Users\86152\Pictures\Saved Pictures\编译生成静态库.png)]

样例代码

  1. vim printHello.h

  2. #ifndef __PRINTHELLO_H__
    #define __PRINTHELLO_H__
    #include <stdio.h>
    void printHello();
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
  3. vim printHello.c

  4. #include <stdio.h>
    void printHello()
    {
        printf("Hello world\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  5. gcc -c printHello.c -o printHello.o

  6. ar rcs libHello.a printHello.o

  7. vim main.c

  8. #include "printHello.h"
    int main()
    {
        printHello();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  9. gcc main.c -o exe -L ./ -lHello

  10. ./exe

编程要求

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

具体编程要求如下:

  • 在当前目录下编写一个简单的函数int Add(int a, int b),其功能为计算输入参数a+b的结果;
  • 将Add函数编译生成一个静态库libAdd.a,并存放在当前目录下;
测试说明

本关的测试需要用户在右侧的命令行下完成,用户只需将需要完成的命令在右侧命令行下直接操作即可,然后点击评测按钮,平台会自动验证用户是否按照要求去检测结果。

  1. vim Add.h

  2. #include <stdio.h>
    int Add(int a, int b);
    
    • 1
    • 2
  3. vim Add.c

  4. #include <stdio.h>
    int Add(int a, int b)
    {
        printf("%d\n", a + b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  5. gcc -c Add.c -o Add.o

  6. ar rcs libAdd.a Add.o

  7. vim main.c

  8. #include "Add.h"
    int main()
    {
        Add(1, 2);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  9. gcc main.c -o out -L ./ -lAdd

  10. ./out

第4关:Linux之动态库编写

任务描述

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

相关知识

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

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

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

生成动态库

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

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

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

案例演示1:

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

  1. vim printHello.h
  2. vim printHello.c
  3. gcc -fPIC -c printHello.c -o printHello.o
  4. gcc -shared printHello.o -o libHello.so
  • 使用vim编写printHello.h(申明printHello函数,方便以后被其它程序调用)
  1. #ifndef __PRINTHELLO_H__
  2. #define __PRINTHELLO_H__
  3. #include <stdio.h>
  4. void printHello();
  5. #endif
  • 使用vim编写printHello.c
  1. #include <stdio.h>
  2. void printHello()
  3. {
  4. printf("Hello world\n");
  5. }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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函数,可以使用如下命令:

  1. vim main.c
  2. gcc main.c -o exe -L ./ -lHello
  3. ./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.cache来运行动态库
  • 编辑/etc/ld.so.conf配置文件,然后加入需要加载的动态库目录。
  • 运行ldconfig更新/etc/ld.so.cache

案例演示1:

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

  1. sudo vim /etc/ld.so.conf
  2. sudo ldconfig
  3. ./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,可以使用如下命令:

  1. LD_LIBRARY_PATH=. ./exe

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vbkuzGnE-1664612753766)(https://data.educoder.net/api/attachments/212815)] [请在右侧“命令行”里直接体验]

注意

  1. LD_LIBRARY_PATH告诉了exe程序现在当前目录下寻找链接的动态库;

  2. 当运行环境中同时存在同名的静态库和动态库时,默认优先链接动态库;

  3. vim printHello.h

  4. #ifndef __PRINTHELLO_H__
    #define __PRINTHELLO_H__
    
    #include <stdio.h>
    
    void printHello();
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  5. vim printHello.c

  6. #include <stdio.h>
    {
    	printf("Hello world\n");
    }
    
    • 1
    • 2
    • 3
    • 4
  7. gcc -fPIC -c printHello.c -o printHello.o

  8. gcc -shared printHello.o -o libHello.so

  9. ls -l libHello.so

  10. [root@hadoop102 样例演示]# ls -l libHello.so
    -rwxr-xr-x. 1 root root 8120 Sep  3 15:16 libHello.so
    
    • 1
    • 2
  11. vim main.c

  12. // 在这里调用的库必须是用双引号好引起来
    #include "printHello.h"
    
    int main()
    {
        printHello();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  13. gcc main.c -o exe -L ./ -lHello

  14. sudo vim /etc/ld.so.conf

  15. ldconfig

  16. LD_LIBRARY_PATH=. ./exe

  17. ./exe

编程要求

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

具体编程要求如下:

  • 在当前目录下编写一个简单的函数int Sub(int a, int b),其功能为计算输入参数a-b的结果;
  • 将Sub函数编译生成一个动态库libSub.so,并存放在当前目录下;
  • 修改/etc/ld.so.conf,添加当前目录,并更新/etc/ld.so.cache
测试说明

本关的测试需要用户在右侧的命令行下完成,用户只需将需要完成的命令在右侧命令行下直接操作即可,然


  1. vim Sub.h

  2. #ifndef __PRINTHELLO_H__
    #define __PRINTHELLO_H__
    
    #include <stdio.h>
    
    int Sub(int a, int b);
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  3. vim Sub.c

  4. #include <stdio.h>
    int Sub(int a, int b)
    {
    	return a - b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  5. gcc -fPIC -c Sub.c -o Sub.o

  6. gcc -shared Sub.o -o libSub.so

  7. vim main.c

  8. #include "Sub.h"
    
    int main()
    {
        printf("%d\n", Sub(2, 1));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  9. vim /etc/ld.so.conf

  10. ldconfig

  11. gcc main.c -o exe -L ./ -lSub

  12. LD_LIBRARY_PATH=. ./exe

  13. ./exe

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/336633?site
推荐阅读
相关标签
  

闽ICP备14008679号