C语言基础14预处理

C语言编译步骤

  • 预处理
  • 编译
  • 汇编
  • 链接

什么是预处理

        预处理就是在源文件(如.c 文件)编译之前,所进行的一部分预备操作,这部分操作是由预处理程序自动来完成;当源文件在编译时,编译器会自动调用预处理程序来完成对预处理指令的解析,预处理指令解析完成才能进入下一步的编译过程。
        我们为了能够方便的看到这个编译细节,我们可以使用下面命令:
gcc 源文件 -E -o 程序名[.后缀]

预处理的功能

宏定义

  • 不带参数的宏定义
    • 语法:
#define 宏名 常量数据
  •         预处理:此时的预处理只做数据替换,不做类型检查
    • 注意:我们定义的宏是不会占用内存空间,还没有到编译环节,就已经被替换成了我们宏中的 常量数据。
    • 宏展开:在预编译时将宏名替换成字符串的过程称为宏展开

案例:

#include <stdio.h> 
#define PI 3.1415926 
void main() 
{ 
float l,s,r,v; 
printf("input radius:"); 
scanf("%f",&r); 
l=2.0*PI*r; 
s=PI*r*r; 
v=4.0/3*PI*r*r*r; 
printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v)
}
  • 带参数的宏定义
  • 语法:
#define 宏名(参数列表) 参数表达式
  • 面试题:
/**
* 宏定义-带参数 
*/ 
#include <stdio.h> 
#define MULTI(a,b) a * b 
int main() 
{ 
int result = MULTI(7+2,3); 
printf("%d\n",result);// 27 9 
return 0; 
} 

  • 宏定义的作用域
    • define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。通常,#define命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。
    • 可以用 undef 命令终止宏定义的作用域
    • 案例
/**
* 宏定义的作用域 
*/ 
#define PI 3.14 
#define DAY 20 
void fun() 
{ 
float r = 4; 
float s = PI * r * r; 
int day = DAY; 
}
#undef PI // 结束PI的作用范围 
#define PI 3.1415926 
void fun1() 
{ 
float r1 = 4; 
float s1 = PI * r1 * r1; 
int day = DAY; 
}
void main() 
{ 
fun(); 
fun1(); 
} 
  • 在宏定义中引用已定义的宏名
案例:
#include <stdio.h> 
#define R 3.0 
#define PI 3.1415926 
#define L 2*PI*R 
#define S PI*R*R 
void main() 
{
printf("L=%f\nS=%f\n",L,S); 
}

文件包含

概念

        所谓“ 文件包含 处理是指一个源文件可以将另外一个源文件的全部内容包含进来。这个适用于多文件开发。

预处理

        此时的预处理,是将文件中的内容替换,文件包含指令。

包含方式

  • 1种: #include <xxxx.h>
    • 系统会到标准库头文件目录(Linux/usr/include )查找包含的文件
  • 2种: #include "xxxx.h"
    • 在当前工程路径下查找,如果未找到,任然会到标准库头文件目录查找

 案例:

        algorithm.h
/**
* 自定义头文件,专门用于存放被外部访问的函数的声明 
*/ 
// 数组的累加和计算 
extern int sum(const int *p,int len);
        algorithm.c
/**
* 实现数组元素的累加计算 
*/ 
int sum(const int *p,int len) 
{ 
int sum = 0; 
register int i = 0; 
for(;i < len; i++) 
{ 
sum += *(p+i); 
}
return sum; 
}
        app.c
// #include <stdio.h> 
// 引入自定义的头文件 
#include "algorithm.h" 
// 如果有n多个外部函数,难道都要一个个的使用extern进行声明? 
// 引入外部函数声明 
// extern int sum(const int*,int); 
int main() 
{ 
int arr[5] = {12,33,14,55,34}; 
int res = sum(arr,5); 
printf("数组累和结果是:%d\n",res); 
return 0; 
} 
编译命令:
gcc algorithm.c app.c -o app // 又包含关系的c文件要一起编译

条件编译

概念

        根据设定的条件选择待编译的语句代码。

预处理

        将满足条件的语句进行保留,不满足条件的语句进行删除,交给下一步编译

语法

语法一

#ifdef 标识 -- 判断标识符定义与否
 .. 
#else
.. 
#endif

语法二

#ifndef 标识 -- 判断标识符定义与否 
.. 
#else
.. 
#endif

语法三

#if 表达式 -- 根据表达式返回的结果:0-不成立,1-成立 
.. 
#else
.. 
#endif 

案例:

/**
* 预处理-条件编译 
*/ 
#define MINUS 1 
int main(void) 
{ 
#ifndef MINUS // 判断标准是:标识有没有被定义
int a = 7 - 4; 
#else
int a = 7 * 4; 
#endif 
printf("计算结果:%d\n",a); 
return 0; 
} 
/**
* 预处理-条件编译:输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输 
出。
*/ 
#include <stdio.h> 
// 定义一个标识 
#define LETTER 0 
void main() 
{ 
// 测试用的字母字符数组 
char str[20] = "C Language"; 
char c; 
int i; 
i = 0; 
while((c=str[i])!='\0') 
{ 
i++; 
#if LETTER 
if(c >='a' && c <='z') 
{ 
c -= 32; 
} 
#else
if(c >='A' && c <='Z') 
{ 
c += 32; 
} 
#endif 
printf("%c",c); 
} 
printf("\n"); 
} 

避免头文件重复包含的方法

语法:

#ifndef __XXXX_H 
#define __XXXX_H 
... 
#endif 

案例:

algorithm.h
/**
* 自定义头文件,专门用于存放被外部访问的函数的声明 
*/ 
#ifndef __ALGORITHM_H 
#define __ALGORITHM_H 
// 数组的累加和计算 
extern int sum(const int *p,int len); 
#endif 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值