C语言程序环境和预处理Pt.2 - 宏的命名约定|#undef|命令行定义|条件编译

本文主要是介绍C语言程序环境和预处理Pt.2 - 宏的命名约定|#undef|命令行定义|条件编译,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Pt1:

C语言程序环境和预处理Pt.1 - 预处理指令|预处理操作符-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/BuiderCodes/article/details/136620859


1.宏的命名约定

  1. 清晰明了:宏的名称应该清晰地表达其功能或目的,使读者能够迅速理解其作用。注意不要使用中文拼音!这样的宏名很难以理解,用英文单词会使读者快速理解。

  2. 使用大写字母:通常约定宏名称全部使用大写字母,以便与函数区别开来,因为函数一般用小写命名,这样能更好区分宏和函数。

  3. 下划线分隔:在多个单词构成的宏名称中使用下划线分隔,以增强可读性。例如:MAX_LENGTH

  4. 避免与关键字冲突:确保宏名称不与语言的关键字或其他已经存在的标识符冲突。

2. #undef 

#undef 是一个预处理器指令,用于取消定义一个已经定义的宏。通过#undef,可以在之后重新定义或者删除已经定义的宏。

例如,运行下面这段代码,将会输出

“MAX”未定义;假设外部返回 int

#define MAX(x,y) ((x)>(y))?(x):(y)
int main()
{int a = 1;int b = 2;int c = MAX(a, b);
#undef MAXint d = MAX(a, b);return 0;
}

3. 命令行

在命令行中,可以使用 -D 选项来定义一个宏。这在编译时可以用来传递参数给预处理器。

例如,在使用 GCC 编译器时,我们可以通过下面这个指令来定义宏:

gcc -DDEBUG main.c -o main

4.条件编译 

条件编译指令是在编译过程中根据预定义的条件选择性地包含或排除代码块。主要的条件编译指令包括:

 #ifdef:检查某个宏是否已经定义,如果定义了,则编译后面的代码块。

#ifdef DEBUG// 在 DEBUG 模式下执行的代码
#endif

要注意,与if不同的是,#ifdef 后面的判断内容不用加括号,而且,if判断为假不会删除代码块里面的内容,而编译指令#ifdel做的事是直接在预处理阶段对条件做判断,为假直接删除代码块内的内容。

#ifndef:与 #ifdef 相反,检查某个宏是否未定义,如果未定义,则编译后面的代码块。

#ifndef DEBUG// 在非 DEBUG 模式下执行的代码
#endif
#ifndef DEBUG// 在非 DEBUG 模式下执行的代码
#endif

#if:基于表达式的结果来选择性地编译代码块。

#if defined(DEBUG) && DEBUG == 1// 在 DEBUG 定义且值为 1 时执行的代码
#endif

#if 决定的是什么条件下编译什么代码,而if决定的是什么情况下执行什么代码。

#elif:在多个条件之间进行选择,与 #if 或 #ifdef 一起使用。

#ifdef DEBUG// 在 DEBUG 模式下执行的代码
#elif defined(TEST)// 在 TEST 模式下执行的代码
#else// 默认情况下执行的代码
#endif

#else与 #ifdef 或 #ifndef 一起使用,指定未满足前面条件时要编译的代码块。

#ifdef DEBUG// 在 DEBUG 模式下执行的代码
#else// 在非 DEBUG 模式下执行的代码
#endif

#endif:结束条件编译块。

#ifdef DEBUG// 在 DEBUG 模式下执行的代码
#endif

 上述指令还可以嵌套使用,比如

#ifdef OS_UNIX#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif
#elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2();#endif	
#endif

条件编译用在开发跨平台应用程序时,可能需要根据不同的操作系统或编译器设置不同的编译选项。条件编译可以根据不同平台的特性选择性地编译适配的代码。

比如一份代码为windows和linux两个平台各写了一份代码,就可以用条件编译指令来编译对应平台的代码。

5.文件包含

C语言中的头文件包含是通过 #include 预处理指令实现的。例如,#include <stdio.h> 将标准输入输出库的声明包含到程序中,使得 printf() 函数可以被使用。

C语言中的包含方法有两种:

  1. 使用尖括号`<>`

    这种方式用于包含标准库头文件或系统提供的头文件。编译器会在系统默认的路径中查找这些头文件。
    如果在系统默认路径下找不到则会报错。
  2. 使用双引号`""`
    这种方式用于包含自定义的头文件或者当前工作目录下的头文件。编译器会先在当前目录下查找头文件,如果找不到再去系统默认路径查找

那是否就是说所有的文件都可以用`""` 来包含呢?

理论上是可以的,但是这样做查找的效率就会变低,而且这样也容易混淆库文件和本地文件。

 现在再来看看这样的情况:

pub.h是公用模块,test1和test2同时调用了pub.h,而test又同时调用了test1 和 test2,这样一来,test.h中就包含了两份pub.h的内容,为了避免这种情况,我们有两种解决方法:

1. 使用条件编译

#ifndef __PUB_H__
#define __PUB_H__//pub.h的内容#endif

我们看到很多系统头文件里面的条件编译语句都是为了防止文件重复包含的。 

 2.使用#pragma once

#pragma once//pub.h的内容

     

这篇关于C语言程序环境和预处理Pt.2 - 宏的命名约定|#undef|命令行定义|条件编译的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/830357

相关文章

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Python如何自动生成环境依赖包requirements

《Python如何自动生成环境依赖包requirements》:本文主要介绍Python如何自动生成环境依赖包requirements问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录生成当前 python 环境 安装的所有依赖包1、命令2、常见问题只生成当前 项目 的所有依赖包1、