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上的编译结果: 输出自定义的错误信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangcoder

赠人玫瑰手有余香,感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值