C语言预处理器使用方法讲解

目录
  • 预处理器实例
  • 预定义宏
  • 预处理器运算符
  • 参数化的宏

C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Preprocessor)简写为 CPP。

所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始。下面列出了所有重要的预处理器指令:

预处理器实例

分析下面的实例来理解不同的指令。

#define MAX_ARRAY_LENGTH 20

这个指令告诉 CPP 把所有的 MAX_ARRAY_LENGTH 定义为 20。使用#define定义常量来增强可读性。

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

这些指令告诉 CPP 从系统库中获取 stdio.h,并添加文本到当前的源文件中。下一行告诉 CPP 从本地目录中获取myheader.h,并添加内容到当前的源文件中。

#undef FILE_SIZE
#define FILE_SIZE 42

这个指令告诉 CPP 取消已定义的 FILE_SIZE,并定义它为 42。

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

这个指令告诉 CPP 只有当 MESSAGE 未定义时,才定义 MESSAGE。

#ifdef DEBUG
   /* Your debugging statements here */
#endif

这个指令告诉 CPP 如果定义了 DEBUG,则执行处理语句。在编译时,如果您向 gcc 编译器传递了-DDEBUG开关量,这个指令就非常有用。它定义了 DEBUG,您可以在编译期间随时开启或关闭调试。

预定义宏

ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。

让我们来尝试下面的实例:

#include <stdio.h>
main()
{
   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );
}

当上面的代码(在文件test.c中)被编译和执行时,它会产生下列结果:

File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1

预处理器运算符

C 预处理器提供了下列的运算符来帮助您创建宏:

宏延续运算符(\)

一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符(\)。例如:

#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")

字符串常量化运算符(#)

在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。例如:

#include <stdio.h>
#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")
int main(void)
{
   message_for(Carole, Debra);
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Carole and Debra: We love you!

标记粘贴运算符(##)

宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。例如:

#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
   int token34 = 40;
   tokenpaster(34);
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

token34 = 40

这是怎么发生的,因为这个实例会从编译器产生下列的实际输出:、

printf ("token34 = %d", token34);

这个实例演示了 token##n 会连接到 token34 中,在这里,我们使用了字符串常量化运算符(#)和标记粘贴运算符(##)。

defined() 运算符

预处理器defined运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的实例演示了 defined() 运算符的用法:

#include <stdio.h>
#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif
int main(void)
{
   printf("Here is the message: %s\n", MESSAGE);
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Here is the message: You wish!

参数化的宏

CPP 一个强大的功能是可以使用参数化的宏来模拟函数。例如,下面的代码是计算一个数的平方:

int square(int x) {
   return x * x;
}

我们可以使用宏重写上面的代码,如下:

#define square(x) ((x) * (x))

在使用带有参数的宏之前,必须使用#define指令定义。参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如:

#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Max between 20 and 10 is 20

到此这篇关于C语言预处理器使用方法讲解的文章就介绍到这了,更多相关C语言预处理器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言零基础彻底掌握预处理下篇

    目录 1.条件编译 1.1 条件编译如何使用 1.2 用 #if 模拟 #ifdef 1.3 为何要有条件编译 2.文件包含 2.1 #include 究竟干了什么 2.2 防止头文件重复包含的条件编译是如何做到的 3.选学内容 3.1 #error 预处理 3.2 #line 预处理 3.3 #pragma 预处理 3.3.1 #pragma message 3.3.2 #pragma once 3.3.3 #pragma warning 3.3.4 #pragma pack 3.4 # 和

  • C语言程序的编译与预处理基础定义讲解

    目录 程序的翻译环境和执行环境 1.翻译环境 2.运行环境 预处理详解 预定义符号 #define #define定义宏 #define替换规则 #和## 带副作用的宏参数 宏和函数对比 命名约定 #undef 命令行定义 条件编译 文件包含 程序的翻译环境和执行环境 在ANSIC的任何一种实现中,存在两个不同的环境:翻译环境和执行环境 翻译环境:源代码被转换为可执行的机器指令. 执行环境:实际执行代码. 1.翻译环境 组成一个程序的每个源文件通过编译分别转换成目标文件(object code)

  • C语言冷知识之预处理字符串操作符详解

    目录 在C语言中什么是标记 预处理字符串操作符 #字符串化操作符 ##标记(Token)连接操作符 当年学习C语言的第一门课就提到过标记(Token)的概念,不过,相信在多年之后你再次听到这个术语时会一脸懵逼,比如我. 因此特地翻了翻资料,整理下来这些笔记. 在C语言中什么是标记 标记是编程语言处理的基本单元,也叫最小划分元素,比如关键字.操作符.变量名.函数名.字符串.数值等等. 下面举例说明一下: printf("hello world!"); 对上面的语句进行标记划分,可分为5个

  • C语言零基础彻底掌握预处理上篇

    目录 1.#define的深度认识 1.1 数值宏常量 1.2 字符串宏常量 1.3 用宏充当注释符号 1.4 用宏替换多条语句 1.5 宏定义的使用建议 2.#undef 撤销宏 2.1 宏的定义位置和有效范围 2.2 宏的取消 2.3 一道笔试题 1.#define的深度认识 1.1 数值宏常量 宏定义数值常量相信大家都不陌生,相信很多小伙伴用过,这里我们就简单的提一下,我们前面也讲过,#define 本质上是替换,它可以出现在代码的任何地方,也可以把任何东西都定义成宏,编译器会在预编译的时

  • C语言深入探究程序的编译之预处理

    目录 1.程序的翻译环境和执行环境 2.详解编译与链接 2.1翻译环境 2.2编译本身也分为几个阶段 2.3运行环境 3.预处理详解 3.1预处理符号 3.2#define 3.2.1#define定义标识符 3.2.2#define定义宏 3.2.3#define的替换规则 3.2.4 宏和函数对比 3.2.5命名约定 3.3#undef 3.4条件编译 1.程序的翻译环境和执行环境 在ANSI C中任何一种实现中,存在两个不同的环境. 第一种是翻译环境,在这个环境中源代码被转换为可执行的机器

  • 一文带你搞懂C语言预处理宏定义

    目录 预定义符号 #define #define 定义标识符 #define 定义宏 替换规则 # 和## 预定义符号 这些预定义符号都是语言内置的 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义 VS环境下未定义__STDC__ ,说明Visual Studio并未完全遵循ANSI C. #define #defi

  • C语言预处理器使用方法讲解

    目录 预处理器实例 预定义宏 预处理器运算符 参数化的宏 C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理.我们将把 C 预处理器(C Preprocessor)简写为 CPP. 所有的预处理器命令都是以井号(#)开头.它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始.下面列出了所有重要的预处理器指令: 预处理器实例 分析下面的实例来理解不同的指令. #defin

  • 易语言设置父窗口的方法讲解

    置父窗口方法 操作系统支持:Windows    所属对象:窗口 设置指定窗口或窗口组件为本对象窗口或窗口组件的父窗口. 语法:  无返回值  窗口组件.置父窗口(父窗口或窗口组件) 例程 运行结果: 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持.如果你想了解更多相关内容请查看下面相关链接

  • 详解C语言编程中预处理器的用法

    预处理最大的标志便是大写,虽然这不是标准,但请你在使用的时候大写,为了自己,也为了后人. 预处理器在一般看来,用得最多的还是宏,这里总结一下预处理器的用法. #include <stdio.h> #define MACRO_OF_MINE #ifdef MACRO_OF_MINE #else #endif 上述五个预处理是最常看见的,第一个代表着包含一个头文件,可以理解为没有它很多功能都无法使用,例如C语言并没有把输入输入纳入标准当中,而是使用库函数来提供,所以只有包含了stdio.h这个头文

  • 前端构建 Less入门(CSS预处理器)

    Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. Less 可以运行在 Node.浏览器和 Rhino 平台上.网上有很多第三方工具帮助你编译 Less 源码. 一.前言 说到前端构建怎能缺少CSS预处理器呢!其实CSS的预处理器有很多啦,比较出名的有Scss.Sass.Stylus和Less.(最近还听说出现了Autoprefixer等CSS后处理器,可参考@一丝的PPT) 众多CSS预处理

  • 深入理解C预处理器

    C 预处理器不是编译器的组成部分,是编译过程中一个单独的步骤.C预处理器只是一个文本替换工具,它会指示编译器在实际编译之前完成所需的预处理. 所有的预处理器命令都是以井号(#)开头.它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始. 下表包含所有重要的预处理器指令: 指令 描述 #define 定义宏 #include 包含一个源代码文件 #undef 取消已定义的宏 #ifdef 如果宏已经定义,则返回真 #ifndef 如果宏没有定义,则返回真 #if 如果给定条件为真,则

  • php实现session自定义会话处理器的方法

    本文实例讲述了php实现session自定义会话处理器的方法.分享给大家供大家参考.具体分析如下: session自定义会话处理器,即就是说,所有关于session的各种操作,都可以通过自定义会话来自己决定.什么意思呢?先来看php.ini里的session.save_handler配置. 默认情况下,session.save_handler = files,表示调用的是系统定义好的处理器(所谓处理器,其实就是一大堆函数/方法).您可从将session.save_handler设置成 user

  • C#中的预处理器指令详解

    目录 1. #define 和 #undef 2. #if.#elif.#else 和#endif 3. #warning 和 #error 4. #region 和#endregion 5. #line 6. #pragma C#中有许多名为"预处理器指令"的命令.这些命令从来不会转化为可执行代码中的命令,但会影响编译过程的各个方面. 例如,使用预处理器指令可以禁止编译器编译代码的某一部分.如果计划发布两个版本的代码,即基本版本和拥有更多功能的企业版本,就可以使用这些预处理器指令.在

  • C#中变量、常量、枚举、预处理器指令知多少

    一.变量 C#共有其中变量类型有:静态变量.实类变量.数组元素.数值参数.引用参数.输出参数和局部变量 先定义一个简单的类来说明,如下: public class VariableDefine { private static uint variableUInt; public static uint VariableUInt { get => variableUInt; set => variableUInt = value; } string VariableStr; public Var

  • vue-loader中引入模板预处理器的实现

    vue-loader 是一个 webpack 的 loader,可以将指定格式编写的 Vue 组件转换为 JavaScript模块 同时,vue-loader 支持使用非默认语言,通过设置语言块的lang属性,就可以使用指定的预处理器,比如最常见的sass 语法: <style lang="sass"> ... </style> 这里重点讨论使用不同的js模板引擎作为预处理器, 下面示例使用了pug模板引擎 <template lang="pug

  • Go语言中如何通过方法为类型添加行为

    前言 数十年以来, 传统的面向对象语言总是说方法属于类, 但 Go 不是这样做的: 它提供了方法, 但是并没有提供类和对象. 乍一看, 这种做法似乎有些奇怪, 甚至可以说有点儿疯狂, 但实际上 Go 的方法比以往其他语言的方法都要灵活. 使用 kelvinToCelsius . celsiusToFahrenheit . fahrenheitToCelsius . celsiusToKelvin 这样的函数虽然也能够完成温度转换工作, 但是通过声明相应的方法并把它们放置到属于自己的地方, 能够让

随机推荐