5.预处理、动态库、静态库

预处理、动态库、静态库

1.C语言编译过程

  1. 预处理

    将.c中的头文件展开、宏展开

    生成的文件是.i文件

  2. 编译

    将预处理之后的.i 文件生成 .s 汇编文件

  3. 汇编

    将 .s 汇编文件生成 .o 目标文件

  4. 链接

    将 .o 文件链接成目标文件

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 4. 链接 (生成可执行文件)

2.include

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

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

  • 注意:include 经常用来包含头文件,可以包含 .c 文件,但是大家不要包含 .c
  • 因为include 包含的文件会在**预编译被展开,如果一个.c 被包含多次,展开多次,会导致函数重定义。 所以不要包含.c** 文件

3.define

  • 定义宏用define 去定义
  • 宏是在预编译的时候进行替换
  1. 不带参宏

    #define PI 3.14

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

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

    注意:宏定义后边不要加分号。

    #define PI 3.1415926
    int main()
    {
    	double f;
    	printf("PI = %lf \n",PI);
    	f = PI;
    	return 0;
    }
    

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

    如果想在中间终止宏的定义范围

    #undef PI  // 终止PI的作用
    
    #define PI 3.1415926  // 定义宏
    int main()
    {
    	double f;
    	printf("PI = %lf \n",PI);
    	#undef PI   // 终止宏
    	#define PI 3.14  // 重新定义宏
    	f = PI;
    	return 0;
    }
    
  2. 带参宏

    #define Name(a,b) a*b

    注意带参宏的形参 a 和 b 没有类型名,

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

    #define Name(a,b) a*b   // 带参宏
    int main()
    {
    	int num;
    	num = Name(2,4);  // num = 2*4
    	num = Name(5,7);  //  num = 5*7
    	num = Name(3+5,7);  // num = 3+5*7  这个就是宏的副作用,跟函数不同,他是直接替换,函数是 8*7
    	return 0;
    }
    
    #define Name(a,b) (a)*(b)   // 带参宏,带上括号
    int main() 
    {
    	int num;
    	num = Name(3+5,7);  // num = (3+5)*(7)  这样就可以解决 3+5*7 的问题了
    	return 0;
    }
    
  3. 带参宏和带参函数的区别

    • 带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈。所以带参宏,就是浪费了空间,因为被展开多次,节省时间
    • 带参函数代码只有一份,存在代码段,调用的时候去代码段取指令,调用的时候要,压栈弹栈。有个调用的过程。
    • 所以所,带参**函数是浪费时间,节省了空间**。

    带参函数的形参是有类型的,带参宏的形参没有类型名。

4.选择性编译

  1. ifdef
#ifdef HongName
	// 如果上面定义过 HongName 这个宏就执行这段代码
#else
	//如果没定义过 执行这段代码
#endif // 结束这个判断
  • 如果在当前 .c ifdef 上边定义过HongName ,就执行上面的代码,否则编译第二个

  • 注意和 if else 语句的区别,if else 语句都会被编译,通过条件选择执行代码,而选择性编译,只有一块代码被编译。

  • 不参加编译的代码块会被注释掉

  • #define HongName
    int main()
    {
    	#ifdef HongName
    	printf("Hello World\n");  // 定义过这个宏,直接执行此代码
    	#else
    	printf("Hello China!!\n");  //这个代码会被注释掉,编译后就没了
    	#endif
    	return 0;
    }
    
    1. ifndef:这个跟 ifdef 正好相反。
#ifndef HongName
	// 如果上面没有定义过 HongName 这个宏,就执行这段代码
#else
	//如果定义过 执行这段代码
#endif // 结束这个判断
  • 这种方法,经常用在防止头文件重复包含

  • 为了方式头文件重复包含,咱们一般敲代码的时候

  • // fun.h  这个是头文件  .h文件
    #ifndef __FUN_H__
    #define __FUN_H__
    extern int fun(int x,int y);
    #endif
    
    3.if
    #if 表达式
    	程序段一
    #else
    	程序段二
    #endif
    
    • 如果表达式为真,编译第一段代码,否则编译第二段代码

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

    • #define AAA  0  // 可以通过AAA的值来执行下边跑哪个代码, 类似于开关
      int main()
      {
      	#if AAA
      	printf("执行第一段代码\n");
      	#else
      	printf("执行第二段代码\n");
      	return 0;
      }
      

5.静态库

  1. 动态编译

    动态编译使用的是动态库文件进行编译

    gcc hello.c -o hello

    默认的咱们使用的是动态编译方法

  2. 静态编译

    静态编译使用的静态库文件进行编译

    gcc -static hello.c -o hello

  3. 静态编译和动态编译的区别

    1. 使用的库文件的格式不一样

      动态编译使用动态库,静态编译使用静态库

    2. 静态编译要把静态库文件打包编译到可执行程序中。(移植到其他电脑上不会报错,体积较大

    3. 动态编译**不会**把动态库文件打包编译到可执行程序中,它只是编译链接关系。(因为是链接关系,所以移动到别的电脑上如果没有动态库文件会报错) 存储容量小

// mylib.c
int max(int a,int b)
{
	return (a > b) ? a : b;
}
int min(int a,int b)
{
    	return (a < b) ? a : b;
}
// mylib.h
#ifndef __MYLIB_H__
#define __MYLIB_H__
extern int max(int a,int b);
extern int min(int a,int b);
#endif
// mytext.c
#include <stdio.h>
#include "mylib.h"

int main()
{
	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;
} 
  • 制作静态库:
  • gcc -c mylib.c -o mylib.o
  • ar rc libname.a mylib.o
  • 注意: 静态库起名的时候必须以lib开头以 .a 结尾
  • 编译方法

6.动态库

无了,,,,,,,,,,,,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值