我想用:
#define
Run Code Online (Sandbox Code Playgroud)
和
#if
Run Code Online (Sandbox Code Playgroud)
允许我在单元测试期间模拟可能缺少的硬件.使用这些#define陈述有哪些规则?
即它的默认范围是什么?我可以改变指令的范围吗?
最初我以为我需要这个,但我最终还是避开了它.然而,我的好奇心(以及对知识,嗡嗡声的兴趣)让我问:
可以是预处理器宏,例如
#include "MyClass.h"
INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
Run Code Online (Sandbox Code Playgroud)
扩展到另一个包括,像在
#include "MyClass.h"
#include "FooTemplate.h"
template class FooTemplate<MyClass>;
Run Code Online (Sandbox Code Playgroud)
?
我从未使用过 #if,#ifdef,#ifnf,#else,#elif和#endif.
当我浏览一些源代码时,我发现了这些指令的广泛使用.对条件预处理器进行了一些阅读,但没有发现它们与正常条件语句的区别.所以我想知道以下代码的优点是什么:
#include<iostream>
int main()
{
int i = 0;
#if i == 0
std::cout<<"This";
#else
std::cout<<"That";
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对此:
#include<iostream>
int main()
{
int i = 0;
if (i == 0)
std::cout<<"This";
else
std::cout<<"That";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此外,什么时候使用 /不使用条件预处理器?
我希望在我的代码中添加一些条件指令来控制不同的构建,例如:
#if VERSION > 100
/* Compiling here */
#endif
Run Code Online (Sandbox Code Playgroud)
问题是"VERSION"在其他代码中我无法改变.它被定义为一个字符串:
#define VERSION "101"
Run Code Online (Sandbox Code Playgroud)
我想知道是否有某种宏或指令将字符串转换为数字,所以我可以简单地做
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Run Code Online (Sandbox Code Playgroud)
这可能吗?
PS.看来我的描述不太清楚.此要求的主要目的是控制版本分支.例如,在旧版本的100版之前,此程序需要old_function().在此版本之后,所有功能都已迁移到new_function.所以我需要编写这样的代码:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
Run Code Online (Sandbox Code Playgroud)
您可以看到只编译了一个函数.因此,必须在预处理阶段决定条件,而不是在运行时.
棘手的部分是,VERSION被定义为一个字符串,它提出了这个问题.
我有两个平台工具集:v110和v110_xp用于我的项目,并且根据所选平台,我想要包含/排除要编译的部分代码.
_MSC_FULL_VER并且$(PlatformToolsetVersion)对于这两个平台工具集具有完全相同的值.或者,我尝试使用$(PlatformToolset)如下:
_MSC_PLATFORM_TOOLSET=$(PlatformToolset)
Run Code Online (Sandbox Code Playgroud)
但问题是这$(PlatformToolset)是非数字的.想知道如何将这个非数字值用作预处理程序指令?
尝试了几种解决方案,我发现了这一点
_MSC_PLATFORM_TOOLSET='$(PlatformToolset)'
Run Code Online (Sandbox Code Playgroud)
然后
#if (_MSC_PLATFORM_TOOLSET=='v110')
[Something]
#endif
Run Code Online (Sandbox Code Playgroud)
工作正常但是
#if(_MSC_PLATFORM_TOOLSET == 'v110_xp')
[SomethingElse]
#endif
Run Code Online (Sandbox Code Playgroud)
导致"字符常量中的字符太多"错误.
有关上下文,请参阅此类似问题: Visual Studio:如何以编程方式检查已使用的C++平台工具集
c++ project-properties preprocessor-directive visual-studio-2012
#pragma packVisual C++中对齐的范围是什么?API参考
https://msdn.microsoft.com/en-us/library/vstudio/2e70t5y1%28v=vs.120%29.aspx
说:
在看到pragma之后,pack在第一个struct,union或class声明生效
因此,以下代码的结果是:
#include <iostream>
#pragma pack(push, 1)
struct FirstExample
{
int intVar; // 4 bytes
char charVar; // 1 byte
};
struct SecondExample
{
int intVar; // 4 bytes
char charVar; // 1 byte
};
void main()
{
printf("Size of the FirstExample is %d\n", sizeof(FirstExample));
printf("Size of the SecondExample is %d\n", sizeof(SecondExample));
}
Run Code Online (Sandbox Code Playgroud)
我曾预料到:
Size of the FirstExample is 5
Size of the SecondExample is 8
Run Code Online (Sandbox Code Playgroud)
但我收到了:
Size of the FirstExample is 5
Size …Run Code Online (Sandbox Code Playgroud) 函数中毒在C++中是非常有用的技术.
一般来说,它指的是使函数不可用,例如,如果你想禁止在程序中使用动态分配,你可能会"毒害" malloc函数,因此无法使用它."中毒"标识符意味着"中毒"后对标识符的任何引用都是硬编译器错误
例如(在此处查看现场演示)
#include <iostream>
#include <cstdlib>
#pragma GCC poison malloc
int main()
{
int* p=(int*)malloc(sizeof(int)); // compiler error use of poisoned function malloc
*p=3;
std::cout<<*p<<'\n';
free(p);
}
Run Code Online (Sandbox Code Playgroud)
我发现这种技术对于防止在C++中滥用保留字非常有用.
例如:
#include "test.h" // contains definition of some class T
#pragma GCC poison private
#define private public // oops compiler error use of poisoned identifier private in macro
int main()
{
// Instantiate T & use it members
}
Run Code Online (Sandbox Code Playgroud)
这也可以在C中用来防止使用C++关键字,因为C++有很多关键字而不是C&C使用C++特定关键字作为C中的标识符是完全有效的.
例如(在此处 …
我对c ++ 11很新,我想知道一些事情......
我正在使用Code :: Blocks,如果我c++11在这个IDE中使用,我必须转到编译器设置,并检查" Have g++ follow the C++11 ISO C++ language standard"
有没有解决方法所以我可以设置一个.cpp文件c++11在这样的#define语句中使用?
注意:这是一个"构建"文件,而不是项目
通过在不在项目中时设置编译选项,它会将其设置为我不希望发生的全局编译选项
我知道您可以自定义它将c++11仅为该项目设置的项目文件中的构建选项
#include <iostream>
#define -std c++11
int main(){
#if __cplusplus==201402L
std::cout << "C++14" << std::endl;
#elif __cplusplus==201103L
std::cout << "C++11" << std::endl;
#else
std::cout << "C++" << std::endl;
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我发现了什么:
更改#define __cplusplus 201103L不是一个好主意,因为它不会将编译器设置为编译为c++11
在C/C++代码中我尝试移植,包括一个不赞成使用的系统头:
从标题:
#ifdef __GNUC__
#warning "this header is deprecated"
#endif
Run Code Online (Sandbox Code Playgroud)
当我们在这里编译时gcc -Wall -Werror,编译停止.从长远来看,替换使用已弃用的函数是最好的,但是现在我想禁用此警告.
编译时没有任何-Werror作用,但由于这是完全自动化构建过程的一部分,我宁愿不这样做.
包括与头#undef荷兰国际集团__GNUC__之前和#define之后荷兰国际集团这是一种可能,但我担心的包含的头里面的副作用.
有没有办法禁用#warning或放松-Werror一个标题?
假设我有
#define Name Joe
Run Code Online (Sandbox Code Playgroud)
有没有办法区分宏的不同值.以下不起作用,但你明白了
#if Name==Joe
// some code
#elif Name==Ben
// some alternative code
#endif
Run Code Online (Sandbox Code Playgroud)
我想用它来生成来自相同源代码的各种目标文件.源差异很小,因此可以很容易地进行宏观控制.宏将通过-DName=Joe编译器标志传入.另请注意,这Name将是一个实际的符号名称,因此我们不能使用基于#define Joe 1等的技巧.
强制编辑请注意,这个类似的问题实际上处理的是字符串值宏.而且那里的答案没有帮助.接受的答案避免了问题(但没有解决),另一个答案strcmp在宏中使用,它依赖于扩展等.