当前位置: 首页 > article >正文

C语言预处理

目录

        1.C语言宏定义define的用法        

        2.C语言文件包含include的用法

        3.C语言条件编译的用法

        4.其他预处理命令


  C语言预处理这一章主要介绍C语言宏定义define的用法、C语言文件包含include的用法、C语言条件编译的用法以及其他预处理命令。预处理命令可以改变程序设计环境,提高编程效率,它们并不是C语言本身的组成部分,不能直接对它们进行编译,必须在对程序进行编译之前,先对程序中这些特殊的命令进行“预处理”。经过预处理后,程序就不再包括预处理命令了,最后再由编译程序对预处理之后的源程序进行编译处理,得到可供执行的目标代码。C语言提供的预处理功能有三种,分别为宏定义、文件包含和条件编译。

1.C语言宏定义define的用法        

  预处理命令可以改变程序设计环境,提高编程效率,它们并不是C语言本身的组成部分,不能直接对它们进行编译,必须在对程序进行编译之前,先对程序中这些特殊的命令进行“预处理”。经过预处理后,程序就不再包括预处理命令了,最后再由编译程序对预处理之后的源程序进行编译处理,得到可供执行的目标代码。C语言提供的预处理功能有三种,分别为宏定义、文件包含和条件编译,下面将对它们进行简单介绍。

  宏定义在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏”,被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的,宏代换是由预处理程序自动完成的。在C语言中,宏分为有参数和无参数两种。无参宏的宏名后不带参数,其定义的一般形式为:

#define 标识符 字符串;

  其中“#”表示这是一条预处理命令(在C语言中凡是以“#”开头的均为预处理命令)“define”为宏定义命令,“标识符”为所定义的宏名,“字符串”可以是常数、表达式、格式串等。符号常量的定义就是一种无参宏定义。
此外,常常对程序中反复使用的表达式进行宏定义。例如:

#define M (y*y+3*y);

它的作用是指定标识符M来代替表达式(y*y+3*y)。

在编写源程序时,所有的(y*y+3*y)都可由M代替,而对源程序进行编译时,将先由预处理程序进行宏代换,即用(y*y+3*y)表达式去置换所有的宏名M,然后再进行编译。

C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对于带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

带参宏定义的一般形式为:

#define 宏名(形参表) 字符串;

在字符串中含有各个形参。

带参宏调用的一般形式为:

宏名(实参表);

例如:

#define M(y) y*y+3*y
/*宏定义*/
......
k=M(5);
/*宏调用*/

......
在上面的宏调用时,用实参5去代替形参y,经预处理宏展开后的语句为:
k=5*5+3*5;
程序2.26给出了一个宏定义和调用的完整实例。
定义一个名为MAX的带参数的宏,可以通过它来选出参数a、b中的较大值:funMax.c。

#include <stdio.h>
#define MAX(a,b) (a>b)?a:b
/*带参数的宏定义*/
int main()
{
    int x,y,max;
    printf("input two numbers: ");
    scanf("%d %d",&x,&y);
    max=MAX(x,y);
    printf("max=%d\n",max);
    /*宏调用*/
    return 0;
};

程序运行结果如下: 

input two numbers: 2009 2010
max=2010

可以看到,宏替换相当于实现了一个函数调用的功能,而事实上,与函数调用相比,宏调用更能提高C程序的执行效率。

2.C语言文件包含include的用法

文件包含
  文件包含是C预处理程序的另一个重要功能,文件包含命令行的一般形式为:

#include "文件名"
或者
#include <文件名>

  文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。

在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程,有些公用的符号常量或宏定义等可单独组成一个文件,在其他文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。


这里对C语言的文件包含命令进行以下几点说明:
  (1)包含命令中的文件名可以用双引号引起来,也可以用尖括号引起来。例如以下写法都是允许的:

#include "stdio.h"
#include <stdio.h>

但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由系统的环境变量进行设置的,一般为系统头文件的默认存放目录,比如Linux系统在/usr/include目录下),而不在源文件的存放目录中查找;使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。

  (2)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。

  (3)文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。

3.C语言条件编译的用法

条件编译 
预处理程序提供了条件编译的功能,可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件,这对于程序的移植和调试是很有用的。条件编译可分为三种形式。

第一种形式如下:

#ifdef 标识符
程序段 1
#else
程序段 2
#endif

它的功能是如果标识符已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
如果没有程序段2(为空),本格式中的#else可以没有,即可以写为:

#ifdef 标识符
程序段
#endif

第二种形式如下:

#ifndef 标识符
程序段 1
#else
程序段 2
#endif

与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。这与第一种形式的功能正好相反。 

第三种形式如下: 

#if 常量表达式
程序段 1
#else
程序段 2
#endif

它的功能是如果常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。
因此可以使程序在不同的条件下完成不同的功能。 

4.其他预处理命令

#error等其他常用预处理命令

除了上面介绍的之外,C语言还有#error、#line、#pragma等其他常用的预处理命令,在很多C语言的程序中也是经常可见的,下面简单介绍一下它们。

1. #error
#error指令强制编译程序停止编译,它主要用于程序调试。#error指令的一般形式是:

#error error-message

注意:宏串error-message不用双引号引起来。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。

2. #line
#line指令改变__LINE__和__FILE__的内容。__LINE__和__FILE__都是编译程序中预定义的标识符。__FILE__的内容是当前被编译源文件的文件名。

#line标识符__LINE__的内容是当前被编译代码行的行号,其一般形式是:

#line number "filename"

其中,number是正整数并变成__LINE__的新值;可选的“filename”是合法文件标识符并变成__FILE__的新值。#line主要用于调试和特殊应用。

3. #pragma
#pragma是编译程序实现时定义的指令,它允许由此向编译程序传入各种指令。例如:一个编译程序可能具有支持跟踪程序执行的选项,此时可以用#pragma语句选择该功能,编译程序忽略其不支持的#pragma选项。使用#pragma预处理命令可提高C源程序对编译程序的可移植性。 

以上就是本章节的内容 有需要关于计算机的问题的可以私信我。 


http://www.kler.cn/news/356149.html

相关文章:

  • 每日一题学习笔记——移动零
  • javaweb以html方式集成富文本编辑器TinyMce
  • Java生死簿管理小系统(简单实现)
  • ORA-12541: TNS: 无监听程序
  • 【python】Pycharm输出窗口自动换行问题
  • Systemd:systemctl 命令
  • 【尚跑】2024咸阳高新区半程马拉松赛141完赛,时隔一年终于pb,天时地利人和的结果
  • 金融信创基金行业案例:某基金公司AD信创替代方案建设分享
  • YOLO11改进 | 注意力机制 | 迈向高质量像素级回归的极化自注意力【全网独家】
  • 基于SpringBoot+Vue+uniapp微信小程序的宿舍报修系统的详细设计和实现
  • 代理 IP:促进在线教育资源普及与公平的新助力
  • 数据仓库构建的两种方法:自上向下、自下向上
  • 《OpenCV计算机视觉》——人脸检测__Haar特征、级联分类器
  • nnUnet 大模型学习笔记(续):训练网络(3d_fullres)以及数据集标签的处理
  • Java项目-基于Springboot的招生管理系统项目(源码+说明).zip
  • 网络变压器在PCIe网口应用的案例
  • 《师兄啊师兄》:家国大义,不忘初心
  • Java项目-基于springboot框架的智能热度分析和自媒体推送平台项目实战(附源码+文档)
  • C++:priority_queue优先队列
  • Spring Boot视频网站:构建高性能的视频服务