Linux-C基础编程

GCC工作流程

工作流程

1.预处理 -E xxx.c —> xxx.i

​ 宏替换;头文件展开;注释去掉;

​ gcc -E hello.c -o hello.i

2.编译 -S xxx.i —> xxx.s #最浪费时间的操作

​ gcc -S hello.i -o hello.s

3.汇编 -C xxx.s —> xxx.o

​ gcc -c hello.s -o hello.o

4.链接 (无参数) xxx.o —> xxx(可执行文件)

​ gcc hello.o -o hello

GCC参数

1
2
3
4
5
6
7
8
9
10
11
12
13
-o 指定生成的文件的名字

-I 编译时,指定头文件的路径 gcc sum.c -I ./include/ -o sum

-c 将汇编文件生成二进制文件(即:.o文件) gcc sum.c -c -I ./include/ #生成sum.o文件

-g gdb调试时,需要加的参数 gcc hello.c -o app -g

-D 在编译时,指定一个[宏] gcc hello.c -I ./include/ -D DEBUG -o hello

-Wall 添加警告(warning)信息

-On 优化代码,n是优化级别:123

库的使用

简介

库是什么

二进制格式的源代码 (.c,.cpp)

以头文件的形式提供给用户使用

静态库和动态库的制作和使用

目录结构
  • test //根目录
    • include //头文件存放位置
      • calc.h //calc头文件
    • lib //存放库文件
      • libadd.a libsum.so //静态库和动态库
    • add.c
    • sum.c
    • main.c
    • Makefile
文件内容
calc.h
1
2
3
4
5
#ifndef __CALC_H__
#define __CALC_H__
int add(int a,int b);
int sum(int a,int b);
#endif
add.c
1
2
3
4
5
6
#include <calc.h>

int add(int a,int b)
{
return (a+b);
}
sum.c
1
2
3
4
5
6
#include <calc.h>

int sum(int a,int b)
{
return (a-b);
}
main.c
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <calc.h>
main()
{
int a=6,b=5;
int the_add=add(a,b);
int the_sum=sum(a,b);
printf("a+b=%d\na-b=%d\n",the_add,the_sum);
}
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
all: main
main: main.c libadd.a libsum.so
gcc main.c -o app -I ./include/ -L ./lib/ -ladd -lsum
lib: libadd.a libsum.so
libadd.a: add.o
ar rcs libadd.a add.o
cp libadd.a ./lib/
add.o: add.c
gcc -c add.c -I ./include/
libsum.so: sum.o
gcc -shared -o libsum.so sum.o
cp libsum.so ./lib/
sum.o: sum.c
gcc -fPIC -c sum.c -o sum.o -I ./include

clean:
rm -rf *.o *.so *.a app

动态库编译运行错误解决办法

在运行生成的二进制文件时可能会报以下错误:

用 ldd 命令查看发现,libsum.so地址找不到

原因
1
file app	#查看可知app是elf格式的可执行程序

对于 elf 格式的可执行程序,是由 ID-linux.so 来完成的

它先搜索 elf 文件的 DT_RPATH 段——环境变量 LD_LIBRARY_PATH——/etc/id.so.cache 文件列表

——/lib/,/usr/lib 目录找到库文件后将其载入内存。

如何让系统找到共享库
临时设置
1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
永久生效

用户级别:

1
2
vi ~/.bashrc		  # 最后一行添加 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
source ~/.bashrc #或者重启终端

系统级别:

修改 /etc/profile 文件

拓展链接:跟我一起写Makefile

标准C库函数和Linux系统函数的区别

c库IO函数的工作流程

Linux系统函数就没有f了

c库函数与系统函数的关系

一些链接:

C标准库和Linux系统函数区别(带不带缓冲区)

Linux系统函数功能目录速查

Linux系统函数参考手册

虚拟地址空间

文件描述符