c语言基础(三)

c语言编译过程(三)

c语言编译过程

1:预处理
将.c 中的头文件展开、宏展开,头文件<stdio.h>声明了大量的函数
生成的文件是.i 文件
2:编译
将预处理之后的.i 文件生成.s 汇编文件
3、汇编
将.s 汇编文件生成.o 目标文件,.o文件是二进制文件
4、链接
将.o 文件链接成目标文件(可执行文件)

visual studio直接生成了可执行文件

Linux 下GCC 编译器编译过程

gcc -E hello.c -o hello.i 1、预处理
gcc -S hello.i -o hello.s 2、编译
gcc -c hello.s -o hello.o 3、汇编
gcc hello.o -o hello_elf 4、链接

[root@localhost caixukun]# cat hello.c
#include<stdio.h>
int main()
{
        printf("hello world\n");
        return 0;
}
[root@localhost caixukun]# ls
hello.c
[root@localhost caixukun]# gcc -E hello.c -o hello.i #1、预处理
[root@localhost caixukun]# gcc -S hello.i -o hello.s #2、编译
[root@localhost caixukun]# gcc -c hello.s -o hello.o #3、汇编
[root@localhost caixukun]# gcc hello.o -o hello      #4、链接
[root@localhost caixukun]# ls
hello  hello.c  hello.i  hello.o  hello.s
[root@localhost caixukun]# ./hello
hello world
[root@localhost caixukun]#

如果.c文件包含了其他.c定义的函数,需要将所有的.c文件进行汇编(生成多个.o文件),最后一起(多个.o文件)链接到一个文件内

gcc 文件1.o 文件2.o 文件3.o -o 文件

预处理

include

include<>//用尖括号包含头文件,在系统指定的路径下找头文件

include “” //用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找。

include 经常用来包含头文件不要包含.c,因为include 包含的文件会在预编译被展开,如果一个.c 被包含多次,展开多次,会导致函数重复定义。所以不要包含.c 文件。

预处理只是对include 等预处理操作进行处理并不会进行语法检查。这个阶段有语法错误也不会报错,第二个阶段即编译阶段才进行语法检查。

define

宏是在预编译的时候进行替换。只要修改宏定义,其他地方在预编译的时候就会重新替换。

#define PI 3.14

在预编译的时候如果代码中出现了PI 就用3.14 去替换。

#define S(a,b) a*b

S(2,4) 将来在预处理的时候替换成实参替代字符串的形参,其他字符保留,2 * 4

宏定义的作用范围,从定义的地方到本文件末尾。

#undef PI //终止PI 的作用

选择性编译

选择性编译都是在编译阶段干的事情。

#ifdef AAA

代码段一

#else

代码段二
#endif

如果在当前.c #ifdef 上边定义过AAA (#define AAA),就编译代码段一,否则编译代码段二

#ifndef AAA

代码段一

#else

代码段二

#endif

和第一种互补。如果在当前.c #ifdef 上边没有定义过AAA ,就编译代码段一,定义过AAA (#define AAA)编译代码段二
这种方法,经常用在防止头文件重复包含。

demo.c
#include<stdio.h>
#include"demo.h"   //包含两遍demo.h头文件
#include"demo.h"

demo.h
#ifndef __demo_h__
#define __demo_h__
extern int num = 3;
#endif // !1
说明demo.c编译#include"demo.h"第一遍时,demo.h中从上至下#ifndef __demo_h__先判断没有定义__demo_h__,执行#define __demo_h__ (定义__demo_h__)extern int num = 3;即第一次编译#include"demo.h"前没有定义__demo_h__,执行完第一次编译#include"demo.h"后定义了__demo_h__。第二变编译#include"demo.h"头文件时:__demo_h__有定义,#ifndef __demo_h__将不会对后面进行编译了

#if 表达式

程序段一

#else

程序段二

#endif

如果表达式为真,编译第一段代码,否则编译第二段代码

#define AAA 0    //定义宏AAA的值决定hello world要不要编译
int main()
{    
    #if AAA
    printf("hello world\n");
    #endif
	return 0;

静态库

一:动态编译
动态编译使用的是动态库文件进行编译
gcc hello.c -o hello
默认的咱们使用的是动态编译方法
二:静态编译
静态编译使用的静态库文件进行编译
gcc -static hello.c -o hello
三:静态编译和动态编译区别
动态编译使用动态库,静态编译使用静态库
**静态编译要把静态库文件打包编译到可执行程序中。**静态编译生成的文件会偏大
动态编译不会把动态库文件打包编译到可执行程序中,它只是编译链接关系

静态库文件

demo.c定义函数

[root@localhost test]# cat demo.c
int max(int x, int y)
{
        return (x > y) ? x : y;
}
int min(int x, int y)
{
        return (x < y) ? x : y;
}

demo.h头文件

[root@localhost test]# cat demo.h
#ifndef __DEMO_H__
#define __DEMO_H__
extern int max(int x, int y);
extern int min(int x, int y);
#endif // !__DEMO_H__

do.c

[root@localhost test]# cat do.c
#include <stdio.h>
#include "demo.h"
int main(int argc, char* argv[])
{
        int a = 10, b = 20, max_num, min_num;
        max_num = max(a, b);
        min_num = min(a, b);
        printf("max_num=%d\n", max_num);
        printf("min_num=%d\n", min_num);
        return 0;
}
[root@localhost test]# gcc -c demo.c -o demo.o  #汇编demo.c汇编成demo.o
[root@localhost test]# ar rc libdemo.a demo.o   #生成静态库文件必须lib开头.a结尾
[root@localhost test]# gcc demo.c do.c -o do    #将两个.c建立链接生成可执行文件do
[root@localhost test]# ./do                     #执行成功
max_num=20
min_num=10
[root@localhost test]# gcc do.c libdemo.a -o doo #将do.c与定义函数源文件的静态库文件建立链接
[root@localhost test]# ./doo
max_num=20
min_num=10
[root@localhost test]# mv demo.h libdemo.a ../text2/
[root@localhost test]# gcc -static-libgfortran do.c -o dooo -L /home/text2/ -l demo -I /home/text2/
[root@localhost test]# ./dooo
max_num=20
min_num=10
-L 是指定库文件的路径
-l 指定找哪个库,指定的只要库文件名lib 后面.a 前面的部分
-I 指定头文件的路径
将库文件及头文件存放到系统默认指定的路径下
库文件默认路径是/lib 或者是/usr/lib
头文件默认路径是/usr/include
gcc -static-libgfortran do.c -o dooo -l demo  #指定静态库文件

动态库

制作动态库文件

[root@localhost test]# gcc -shared demo.c -o libdemo.so
[root@localhost caixukun]# gcc do.c libdemo.so -o do
[root@localhost caixukun]# ./do
./do: error while loading shared libraries: libdemo.so: cannot open shared object file: No such file or directory   #找不到动态库文件,需要增加LD_LIBRARY_PATH的环境变量
[root@localhost caixukun]# export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
[root@localhost caixukun]# ./do
max_num=20
min_num=10
也可以使用gcc指定文件夹,生成可执行程序,
-L 是指定库文件的路径
-l 指定找哪个库,指定的只要库文件名lib 后面.a 前面的部分
-I 指定头文件的路径
同样如果找不到动态库文件,也需要增加LD_LIBRARY_PATH的环境变量
库函数、头文件均在系统路径下
库文件 /usr/lib
头文件 /usr/include
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值