C语言——程序环境和预处理(下)

简介: C语言——程序环境和预处理(下)

3. 预处理详解


3.1 预定义符号

__FILE__      //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__    //文件被编译的日期
__TIME__    //文件被编译的时间
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

这些预定义符号都是语言内置的。

举个栗子:

printf("file:%s line:%d\n", __FILE__, __LINE__);

3.2 #define

3.2.1 #define 定义标识符

语法:

#define name stuff

举个栗子:

#define MAX 1000
#define reg register          //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;)     //用更形象的符号来替换一种实现
#define CASE break;case        //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
                          date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ ,       \
__DATE__,__TIME__ )

提问:

        在define定义标识符的时候,要不要在最后加上 ?

比如:

#define MAX 1000;

#define MAX 1000

建议不要加上 ; ,这样容易导致问题。

比如下面的场景:

if(condition)
 max = MAX;
else
 max = 0;

这里会出现语法错误


3.2.2 #define 替换规则

       在程序中扩展#define定义符号和宏时,需要涉及几个步骤。


1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。


2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。


3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。


注意:


1. 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归。


2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。


3.2.3宏和函数对比


宏通常被应用于执行简单的运算。比如在两个数中找出较大的一个。


#define MAX(a, b) ((a)>(b)?(a):(b))

那为什么不用函数来完成这个任务?


原因有二:


1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比 函数在程序的规模和速度方面更胜一筹。

2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之 这个宏怎可以适用于整形、长整型、浮点型等可以用于>来比较的类型。宏是类型无关的。

当然和宏相比函数也有劣势的地方:


        1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。

       2. 宏是没法调试的。


        3. 宏由于类型无关,也就不够严谨。


        4. 宏可能会带来运算符优先级的问题,导致程容易出现错。

宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到

#define MALLOC(num, type)\
 (type *)malloc(num * sizeof(type))
...
//使用
MALLOC(10, int);//类型作为参数
//预处理器替换之后:
(int *)malloc(10 * sizeof(int));

宏和函数的一个对比

f822040e220b4fea8a1473c7cc526edd.png

命名约定 一般来讲函数的宏的使用语法很相似。


所以语言本身没法帮我们区分二者。


那我们平时的一个习惯是:


把宏名全部大写

函数名不要全部大写


4. 其他预处理指令


#error


#pragma


#line ...


不做介绍,自己去了解。


#pragma


pack()在结构体部分介绍  


相关文章
|
1月前
|
C语言 索引
C语言编译环境中的 调试功能及常见错误提示
这篇文章介绍了C语言编译环境中的调试功能,包括快捷键操作、块操作、查找替换等,并详细分析了编译中常见的错误类型及其解决方法,同时提供了常见错误信息的索引供参考。
|
1月前
|
存储 算法 C语言
"揭秘C语言中的王者之树——红黑树:一场数据结构与算法的华丽舞蹈,让你的程序效率飙升,直击性能巅峰!"
【8月更文挑战第20天】红黑树是自平衡二叉查找树,通过旋转和重着色保持平衡,确保高效执行插入、删除和查找操作,时间复杂度为O(log n)。本文介绍红黑树的基本属性、存储结构及其C语言实现。红黑树遵循五项基本规则以保持平衡状态。在C语言中,节点包含数据、颜色、父节点和子节点指针。文章提供了一个示例代码框架,用于创建节点、插入节点并执行必要的修复操作以维护红黑树的特性。
49 1
|
1月前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
65 1
|
29天前
|
编译器 C语言 计算机视觉
C语言实现的图像处理程序
C语言实现的图像处理程序
52 0
|
13天前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
28 10
|
17天前
|
Shell Linux API
C语言在linux环境下执行终端命令
本文介绍了在Linux环境下使用C语言执行终端命令的方法。首先,文章描述了`system()`函数,其可以直接执行shell命令并返回结果。接着介绍了更强大的`popen()`函数,它允许程序与命令行命令交互,并详细说明了如何使用此函数及其配套的`pclose()`函数。此外,还讲解了`fork()`和`exec`系列函数,前者创建新进程,后者替换当前进程执行文件。最后,对比了`system()`与`exec`系列函数的区别,并针对不同场景推荐了合适的函数选择。
|
1月前
|
存储 自然语言处理 程序员
【C语言】文件的编译链接和预处理
【C语言】文件的编译链接和预处理
|
28天前
|
程序员 编译器 C语言
C语言中的预处理指令及其实际应用
C语言中的预处理指令及其实际应用
55 0
|
C语言
C语言及程序设计初步例程-4 C语言程序初体验
贺老师教学链接  C语言及程序设计初步 本课讲解 让程序会计算:求a和b两个数之和 #include <stdio.h> int main( ) { int a,b,sum; scanf("%d %d", &a, &b); sum=a+b; printf("%d\n", sum); return 0; } 用户界面友好(或罗
1078 0
|
C语言 数据处理
《C语言及程序设计》实践项目——C语言程序初体验
返回:贺老师课程教学链接  C语言及程序设计初步   【项目1-输出点阵图】编一个程序,用你的姓名读音首字母,组成类似的趣图提示:printf("……\n");语句会输出双引号中的内容,'\n'完成换行[参考解答]【项目2-完成简单计算】(1)编程序,输入长方形的两边长a和b,输出长方形的周长和面积 提示:边长可以是整数也可以是小数;实现乘法的运算符是*[参考解答] (2)编程序,输入两个电
1258 0