欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 96.【C语言】解析预处理(4)

96.【C语言】解析预处理(4)

2025/7/15 17:33:28 来源:https://blog.csdn.net/2401_85828611/article/details/145807809  浏览:    关键词:96.【C语言】解析预处理(4)

目录

5.条件编译

#ifdef

其他条件编译指令

#if

多个分支的条件编译

判断是否被定义

嵌套指令

6.头文件的包含方式

本地文件包含

库文件包含

嵌套文件包含

问题:头文件的重复包含

解决问题:避免头文件的重复包含

方法1:#pragma once

方法2:#ifndef、#define和#endif

画图分析

7.其他预处理指令

#error


承接95.【C语言】解析预处理(3)文章

5.条件编译

即选择性编译,某些情况下需要编译,而某些情况下不需要编译,常见的是调试代码

#ifdef

#include <stdio.h>
#define __DEBUG__
int main()
{int arr[10];for (int i = 0; i < 10; i++){arr[i] = i;
#ifdef __DEBUG__printf("arr[%d]=%d\n", i, arr[i]);//检查是否正常赋值
#endif // __DEBUG__}return 0;
}

解释:#ifdef __DEBUG__ 表示是否定义了__DEBUG__,#endif表示结束一个条件编译块

如果有#define __DEBUG__ 则执行条件编译,否则不执行

其他条件编译指令

#if

#if 常量表达式
//...
#endif

例如微软提供的stdio.h中有如下代码

#if __STDC_WANT_SECURE_LIB__#define L_tmpnam_s L_tmpnam
#endif

解释: 如果__STDC_WANT_SECURE_LIB__值为,则定义#define L_tmpnam_s L_tmpnam

多个分支的条件编译

#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif

例如某项目下有如下代码(参见)

#ifdef ENABLE_NLS
#include <libintl.h>
#else
#define gettext(x) (x)
#endif

如果定义了ENABLE_NLS,则包含libintl.h,否则定义#define gettext(x) (x)

判断是否被定义

#if defined(symbol)等价写法为#ifdef symbol

#if !defined(symbol)等价写法为#ifndef symbol

例如微软的<stdlib.h>中有如下代码

#ifndef _countof#define _countof __crt_countof
#endif

(#ifndef全称if not define)

解释:如果没有定义 _countof,则定义#define_countof __crt_countof

嵌套指令

例如某项目下有如下代码(参见GitHub mir/mir.c)

#if defined(__x86_64__) || defined(_M_AMD64)
#include "mir-x86_64.c"
#elif defined(__aarch64__)
#include "mir-aarch64.c"
#elif defined(__PPC64__)
#include "mir-ppc64.c"
#elif defined(__s390x__)
#include "mir-s390x.c"
//......
#else
#error "undefined or unsupported generation target"
#endif

defined()用于检查某个宏是否已经被定义 

上段代码是根据目标系统的处理器架构包含不同的源文件

#if defined(__x86_64__) || defined(_M_AMD64) 即如果是x86_64架构,则包含mir-x86_64.c文件

#elif defined(__aarch64__) 是否是aarch64架构? 如果是则包含mir-aarch64.c

......(后面的类似不分析)

6.头文件的包含方式

本地文件包含

#include "xxxxxx" //使用双引号

先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在
标准位置查找头文件

标准位置:

Linux: /usr/include

VS2022: 默认路径为C:\Program Files (x86)\Windows Kits\10\Include

库文件包含

#include <xxxxxx> //使用尖括号

直接去标准路径下去查找,如果找不到就提示编译错误

不建议使用双引号去包含库文件,否则消耗库文件的寻找时间

嵌套文件包含

问题:头文件的重复包含

例如:test.h中写入:

void test_func();

main.c写入:

#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
int main()
{return 0;
}

Linux下编译头文件会包含5次,文件体积变大

解决问题:避免头文件的重复包含

方法1:#pragma once

即只包含一次,将#pragma once写入头文件中,再预处理生成i文件,发现test.h只包含一次

方法2:#ifndef、#define和#endif

格式:

#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif //__TEST_H__

例如test.c包含两次test.h,展开头文件后为

#ifndef __TEST_H__
#define __TEST_H__
void test_func();
#endif //__TEST_H__
#ifndef __TEST_H__
#define __TEST_H__
void test_func();
#endif //__TEST_H__
int main()
{return 0;
}

 将代码粘贴到VS上看看,会发现字体的颜色深浅不同

画图分析

7.其他预处理指令

#error

作用:预处理到#error命令时将停止编译并输出用户自定义的错误消息

例如某项目中有如下代码(参见GitHub ruby/st.c)

#if MINIMAL_POWER2 < 2
#error "MINIMAL_POWER2 should be >= 2"
#endif

将上方的代码添加到自己写的c文件中,调试看看

#define MINIMAL_POWER2 1
#if MINIMAL_POWER2 < 2
#error "MINIMAL_POWER2 should be >= 2"
#endif
int main()
{return 0;
}

VS上的编译结果: 输出自定义的错误信息

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词