举出下面的例子代码如下↓ 在这里会举出两个例子①参与编译、②不参与编译。...在这里我们先举出第②个例子↓ #include int main(void) { #ifdef PRINT printf("hello C"); #endif } 运行结果如下↓...无,那么这个是为什么呢。...如果表达式的值为真,则编译后面的代码直到出现 #else、#elif 或 #endif 为止,否则不编译。 #endif指令 该指令用于终止 #if 指令。...大家可以自己上手用代码描述一下。 ⒊条件编译在哪些地方使用? 通常用于中大型项目当中会使用到条件编译以及版本之间的维护(某某软件完全版和精简版)当然条件编译还可以完成一些其它的事情。
,为什么要用这些呢?...而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。 例如: 假设你的工程里面有4个文件,分别是a.cpp,b.h,c.h,d.h。...加上ifndef/define/endif,就可以防止这种重定义错误。 所以还是把头文件的内容都放在#ifndef和#endif中吧。 不管你的头文件会不会被多个文件引用,你都要加上这个。...一般格式是这样的: #ifndef #define …… …… #endif 在理论上来说可以是自由命名的,但每个头文件的这个...…… #endif 2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。
#define定义宏 #undef取消已定义的宏 #if如果给定条件为真,则编译下面代码 #ifdef如果宏已经定义,则编译下面代码 #ifndef如果宏没有定义,则编译下面代码...#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。...在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。 #ifndef的方式受C/C++语言标准支持。...它不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含。...#else // ... statement #endif 常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏, 那么它的值被视为0。
宏名的选择可以使用文件名的某种形式,比如 _THREAD_HPP__ 对应的是 Thread.hpp 文件,或者使用其他自定义的宏名称 ① #ifndef _THREAD_HPP__ #ifndef...定义这个宏后,后续的 #ifndef _THREAD_HPP__ 检查就会失败,代码就不会重复包含头文件的内容。...③ #endif #endif 用来结束 #ifndef 或 #if 语句的条件块。它告诉编译器在这里结束这个条件的作用域 ④ 作用 这种头文件保护机制的作用是: 防止头文件被多次包含。...,并且一个线程在运行时被多个线程访问,shared_ptr 会保证对象在所有线程之间共享时依然能正确管理内存。...因此,每个线程可以根据需要处理不同类型的数据,增强了代码的灵活性和通用性。 值得注意的是:为什么 using 定义类型别名要放到类里面?
如果想使局部变量的值在程序的整个生命期里仍然存在,我们可以定义函数的局部变量为static(静态的),并给它一个初始化。...初始化只在函数第一次调用时执行,函数调用之间变量的值保持不变,这种方式,函数可以“记住”函数调用之间的一些信息片断。...我们可能奇怪为什么不使用全局变量。static局部变量的优点是在函数范围之外它是不可用的,所以它不可能被轻易改变。这会使错误局部化。...一、关键字:#ifndef,#define,#endif可以防止头文件被重复引用 结构是这样的: 如a.h头文件 #ifndef XX #define XX // 函数声明 #endif 第一次...;那么当编译到第二次#inlude的地方的时候由于不满足 #ifndef XX这个判断条件所以不执行后面的内容(#define XX和函数声明都不走)直接跳到#endif因此可以很好的防止头文件被重复引用
假定你需要创建一个实时的控制程序,需要一直在后台运行着,而你的客户端却是多个或多样性,客户端的开发语言不确定性。这就需要创建一个 COM 服务进程程序。...其它的一些工具我们需要准备的注册工具 GuiRegsvrCE.exe 用于注册你的 COM DLLs 这类工具可以在网上搜索到 创建 COM Server 由于 Windows CE...不支持自动化列集 / 散集,因此我们需要建立自己的代理 / 存根,用与 COM Server 和 Client 之间的接口方法参数的列集与散集。...MIDL 开关 /Oicf 时定义 #ifndef _WIN32_WCE #pragma comment(lib, "rpcns4.lib") #endif #pragma comment(lib,...在这里我提供了一些辅助代码《EventHandler.h》,协助客户端在不使用 ATL 情况下接受 COM Server 的事件。 ?
可以参考如下:首先,头文件可以通过#include预处理的方式包含进源文件,可以在预处理阶段展开进行预处理,比如使用#ifndef等预处理指令判断头文件中的内容是否已经被定义(可能会多次展开同一个头文件...),如果是的话,那么在编译的阶段就不会对相同的内容重复编译,如此便可提高编译的性能效率;其次,将具有特定功能的程序归为一类封装在同一个头文件中,可以形成模块化编程,也能很大地提高代码的共享性和复用性,以及维护管理的便捷性...、#define和#endif,用于防止重复编译;第三,在#define和#endif之间,添加需要的声明和定义;头文件的结构可参考如下:#infdef TEST_H#define TEST_H//添加需要的声明和定义...#endif头文件结构分析TEST_H:其实就是test.h头文件的名称转变而成的,这是一个标识符,应当具有唯一性,即与其它的头文件不一样,用于避免重复编译;#define TEST_H后面为什么没有向其它的宏定义一样紧跟着宏的...#include "stdio.h"#include "test.h"int main() { test(); return 0;}代码编译运行,得到输出:Hello, World原文(及后续章节
如果我们要求程序需要满足在不同的平台上均能正确的运行,不会因为整型数据范围不同而产生数据溢出。那么,我们可以为整型取一些别名。 作用范围 别名如果定义在代码块中,那么它就具有块作用域。...那么,文件person.h中的Person结构类型也需要相应的调整。否则,两边的 Person 不一致,虽然可以通过编译,但是运行时将有可能发生崩溃。 如果能让它们使用同一份代码就比较完美了。...#define PERSON_H戳,用于记录是否定义 预处理指令#ifndef用于测试其后跟着的宏是否没有被定义。 若没有被定义,则保留从#ifndef到#endif之间的代码。...若被定义,则删除从#ifndef到#endif之间的代码。...因此,将保留从#ifndef PERSON_H开始,直到#endif的代码。而这段代码内,定义了宏PERSON_H。
抽象类 上述引出了纯虚函数的写法,那纯虚函数和抽象类之间有什么关系呢?实际上,抽象类就是具有纯虚函数的类,那这抽象类存在的意义是什么呢?...: [image-20210222103409774] 可以看到上述有6个文件,我们首先来看 Chinese.h这个文件,代码如下所示: #ifndef _CHINESE_H #define _CHINESE_H...通过上述地.h文件可以看出,在这里的Chinese类中,它只涉及到类成员函数的一个声明,并没有成员函数的实现,我们继续来看Chinese.cpp的类实现: #include "Chinese.h"...,比如说Chinese和Englishman都有名字,那么就可以增添设置名字和获取名字这两种方法,首先是 Chinese的代码,代码如下: #ifndef _CHINESE_H #define _CHINESE_H...::getName(void) { return this->name; } 有了 Human类之后,我们就可以来实现我们所说的 Englishman和Chinese类了,代码如下所示: #ifndef
抽象类 上述引出了纯虚函数的写法,那纯虚函数和抽象类之间有什么关系呢?实际上,抽象类就是具有纯虚函数的类,那这抽象类存在的意义是什么呢?...image-20210222103409774 可以看到上述有6个文件,我们首先来看 Chinese.h这个文件,代码如下所示: #ifndef _CHINESE_H #define _CHINESE_H...通过上述地.h文件可以看出,在这里的Chinese类中,它只涉及到类成员函数的一个声明,并没有成员函数的实现,我们继续来看Chinese.cpp的类实现: #include "Chinese.h"...image-20210223190725028 在上述中,我们看到编译我们是用make命令进行编译的,然后在运行可执行代码的时候,我们采用的是LD_LIBRARY_PATH=./ ....小结 上述便是本期教程的所有内容,教程所涉及的代码可以通过百度云链接的方式获取。
可以通过使用预处理器指令(如 #ifndef、#define、#endif 结构或者 #pragma once 指令)来解决头文件的重复包含问题,从而确保每个头文件只被包含一次。...#ifdef identifier // 如果 identifier 已定义,则执行此处的代码 #endif 或者你可以与 #ifndef(如果未定义)和 #else(如果未定义则执行另一段代码...#endif 这通常用于在编译时根据不同条件选择性地包含或排除代码块。...当然ifdef也可以和else连起来使用,以及#elif #elif 是条件预处理指令的一部分,用于在多个条件之间进行选择。...虽然在#ifdef结构中可以使用#elif,但是需要注意的是,#elif 是 #else 和 #if 或者 #ifdef 或者 #ifndef 的结合,而不是 #ifndef 的一部分。
/*...*/ #ifdef __cplusplus } #endif #endif /* __INCvxWorksh */ 分析:显然,头文件中的编译宏“#ifndef...extern "C" int foo( int x, int y ); #endif 在模块B的实现文件中仍然调用foo( 2,3 ),其结果是: (1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理...我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题): 实现C++与C及其它语言的混合编程。...笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下: /* c语言头文件:cExample.h */ #ifndef C_EXAMPLE_H #define C_EXAMPLE_H extern...笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下: //C++头文件 cppExample.h #ifndef CPP_EXAMPLE_H #define CPP_EXAMPLE_H extern
#endif •1>如果条件1成立,那么编译器就会把#if 与 #elif之间的code1代码编译进去(注意:是编译进去,不是执行,很平时用的if-else是不一样的)2> 如果条件1不成立、条件2成立...,那么编译器就会把#elif 与 #else之间的code2代码编译进去 •3> 如果条件1、2都不成立,那么编译器就会把#else 与 #endif之间的code3编译进去 •4> 注意,条件编译结束后...,要在最后面加一个#endif,不然后果很严重(自己思考一下后果) •5> #if 和 #elif后面的条件一般是判断宏定义而不是判断变量,因为条件编译是在编译之前做的判断,宏定义也是编译之前定义的,而变量是在运行时才产生的...#endif •如果前面已经定义过MAX这个宏,就将code编译进去。它不会管MAX的值是多少,只要定义过MAX,条件就成立。 条件也可以取反: #if !...#endif •如果前面已经定义过MAX这个宏,就将code编译进去。 •* #ifndef又和#if !defined()的用法基本一致 #ifndef MAX ...code...
#if和#ifdef之间的区别。...#endif 它的作用是:如果(MAX==10)||(MAX==20)成立,那么编译器就会把其中的#if 与 #endif之间的代码编译进去(注意:是编译进去,不是执行!!)...#endif 这个#ifdef 它不管里面的“x”的逻辑是“真”还是“假”,它只管这个程序前面的宏定义里面有没有定义“x”这个宏(即在这里#define x 1和#define x 0等效,都等同于...#if defined的使用 #if defined() 的使用和#ifdef的用法一致 #if !defined()又和 #ifndef 的用法一致。...最后强调两点: 第一:这几个宏定义只是决定代码块是否被编译! 第二:别忘了#endif 明白了之间的区别问题就变得非常的容易,修改上述代码只要把其中的#ifdef改成#if就可以达到目的。
,所以不会再重复执行“头文件内容”部分的代码。...除此之外,#pragma once 只能作用于某个具体的文件,而无法向 #ifndef 那样仅作用于指定的一段代码。...事实上,无论是 C 语言还是 C++,为防止用户重复引入系统库文件,几乎所有库文件中都采用了以上 3 种结构中的一种,这也是为什么重复引入系统库文件编译器也不会报错的原因。...除非对项目的编译效率有严格的要求,强烈推荐读者选用第一种解决方案,即采用 #ifndef / #define / #endif 组合解决头文件被重复引入。...比如说: #pragma once #ifndef _STUDENT_H #define _STUDENT_H class Student { //...... }; #endif 当编译器可以识别
条件指示符#ifndef检查预编译常量在前面是否已经被定义.如果在前面没有被定义,则条件指示符的值为真,于是从#inndef到#endif之间的所有语句都被包含进来进行处理.相反,如果#inndef指示符的值为假...,则它与#endif指示符之间的行将被忽略.条件指示符#ifndef的最主要目的是防止头文件的重复包含和编译。 ...深入:条件编译 预处理程序提供了条件编译的功能。 可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。...如果没有程序段2(它为空),本格式中的#else可以没有,即可以写为: #ifdef 标识符 程序段 #endif ...而在程序的第一行已对NUM作过宏定义, 因此应对第一个printf语句作编译故运行结果是输出了学号和成绩。
命令只能包含一个头文件 2、同一个头文件可以被多次引入,多次引入的效果和一次引入的效果相同,因为头文件在代码层面有防止重复引入的机制 3、头文件包含允许嵌套 (头文件只能包含变量和函数的声明,不能包含定义...,则执行程序段1,否则继续往后判断依次类推(注意是整形常量表达式),最后#endif是#if的结束标志 代码示例: 1 #include "stdio.h" 2 3 #define MAX 10...,如果该宏已经定义则执行后面的代码,一般使用格式如下 #ifdef 宏名 程序段1 #else 程序段2 #endif 它的意思是,如果该宏已被定义过,则对程序段1进行编译,否则对程序段...2进行编译(这个和上面的#if一样最后都需要#endif),上述格式也可以不用#else,这一点上和if else相同 代码示例: 1 #include 2 3 #define...,需要知道的就是#endif是#if, #ifdef, #ifndef这些条件命令的结束标志.这里就不再赘述了 上面说了8种预处理命令,下面再补充一个预处理函数(注意是函数且该函数有返回值) defined
前言 如何在C++代码中调用写好的C接口?你可能会奇怪,C++不是兼容C吗?直接调用不就可以了,那么我们来测试一下,先看看C++如何调用C代码接口的。...那么g++编译器为什么找不到print(int,int)呢,其实在我们学C++重载的时候就提到过C++底层的编译原理。...g++ 进行链接,也就是 C++ 链接方式,程序在运行到调用 print 函数的代码时,会在符号表中寻找 _Z5printii(是按照C++的链接方法来寻找的,所以是找 _Z5printii 而不是找...extern “C” ,这个时候,g++编译器就会按照C语言的链接方式进行寻找,也就是在符号表中寻找print(这才是C++兼容C),这个时候是可以找到的,是不会报错的。...} #endif #endif /* __cplusplus */ #endif /* __TEST_H__ */ ps:下期介绍一个Source Insight的插件,快速生成上面的代码 再次执行命令
A如果没有定义A就执行下面的语句 #define #define MAX_SIZE 10 定义(定义一个字符常量)程序中所有的MAX_SIZE都被10代替(可以让10这个常量更有意义) #endif...与#ifndef配对,开始,结束 所有头文件必须包含下面三句话(模版): #ifndef 头文件名_H #define 头文件名_H … … 函数声明或者宏定义、全局变量、结构体类型 #endif 三...3.建议一个头文件add.h,咱们先完成这个里面的代码:如下 #ifndef ADD_H #define ADD_H int add(int a,int b); #endif 代码说明请参考上边讲的预处理的介绍...a+b; } 这里说下为什么要引入自己的头文件,主要是因为如果存在多个相互调用的子函数,那就需要进行函数声明,这时需要引入自己的头文件就行了,如果头文件没有包含,需要补写函数声明。...)); } 编译一下,没有任何错误,运行结果为: ?
领取专属 10元无门槛券
手把手带您无忧上云