我一直在查看Boost库的源代码,我注意到通常只有单个符号没有附加任何预处理器指令.我阅读了GCC预处理器手册和规范指南,但没有找到任何相关信息.
(1) #ifndef BOOST_CONFIG_HPP
(2) # include <boost/config.hpp>
(3) #endif
(4) #
(5) #if defined(BOOST_HAS_PRAGMA_ONCE)
(6) # pragma once
(7) #endif
Run Code Online (Sandbox Code Playgroud)
在第4行,英镑符号后没有任何内容.这有什么影响?它是在C预处理器(CPP)规范中定义的吗?
由于Boost是一个跨平台的库,我认为任何CPP都应该正确解析它.在整个代码中使用随机井号/井号的影响/副作用是什么?
我正在尝试编写一个程序,其中一些函数的名称依赖于某个宏变量的值,宏如下:
#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE
int NAME(some_function)(int a);
Run Code Online (Sandbox Code Playgroud)
不幸的是,宏NAME()将其转化为
int some_function_VARIABLE(int a);
Run Code Online (Sandbox Code Playgroud)
而不是
int some_function_3(int a);
Run Code Online (Sandbox Code Playgroud)
所以这显然是错误的方式.幸运的是,VARIABLE的不同可能值的数量很小所以我可以简单地做一个#if VARIABLE == n并单独列出所有情况,但我想知道是否有一个聪明的方法来做到这一点.
例:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
Run Code Online (Sandbox Code Playgroud)
BAR()根据C99标准,上述用途确实不正确,因为它将扩展到:
printf("this breaks!",);
Run Code Online (Sandbox Code Playgroud)
请注意尾随逗号 - 不可行.
一些编译器(例如:Visual Studio 2010)将悄然摆脱那个尾随的逗号.其他编译器(例如:GCC)支持放在##前面__VA_ARGS__,如下所示:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
但有没有符合标准的方法来获得这种行为?也许使用多个宏?
现在,该##版本似乎得到了相当好的支持(至少在我的平台上),但我真的更喜欢使用符合标准的解决方案.
先发制人:我知道我可以写一个小功能.我正在尝试使用宏来做到这一点.
编辑:以下是我想要使用BAR()的一个例子(虽然简单):
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
Run Code Online (Sandbox Code Playgroud)
这会自动为我的BAR()日志记录语句添加换行符,假设fmt它始终是双引号C字符串.它不会将换行符打印为单独的printf(),如果日志记录是行缓冲的并且异步来自多个源,则这是有利的.
在我正在研究的C++项目中,我有一个标志值,它可以有四个值.这四个标志可以组合在一起.标志描述数据库中的记录,可以是:
现在,对于我希望保留此属性的每条记录,我可以使用枚举:
enum { xNew, xDeleted, xModified, xExisting }
Run Code Online (Sandbox Code Playgroud)
但是,在代码的其他地方,我需要选择哪些记录对用户可见,所以我希望能够将其作为单个参数传递,如:
showRecords(xNew | xDeleted);
Run Code Online (Sandbox Code Playgroud)
所以,似乎我有三个可能的附件:
#define X_NEW 0x01
#define X_DELETED 0x02
#define X_MODIFIED 0x04
#define X_EXISTING 0x08
Run Code Online (Sandbox Code Playgroud)
要么
typedef enum { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } RecordType;
Run Code Online (Sandbox Code Playgroud)
要么
namespace RecordType {
static const uint8 xNew = 1;
static const uint8 xDeleted = 2;
static const uint8 xModified = 4;
static const uint8 xExisting = 8;
}
Run Code Online (Sandbox Code Playgroud)
空间要求很重要(字节与整数),但并不重要.使用定义我失去了类型安全性,并且enum我失去了一些空间(整数),并且当我想要进行按位操作时可能需要进行转换.随着 …
有没有办法在编译时将整个文本文件作为字符串包含在C程序中?
就像是:
file.txt的:
This is
a little
text file
Run Code Online (Sandbox Code Playgroud)main.c中:
#include <stdio.h>
int main(void) {
#blackmagicinclude("file.txt", content)
/*
equiv: char[] content = "This is\na little\ntext file";
*/
printf("%s", content);
}
Run Code Online (Sandbox Code Playgroud)获取一个在stdout上打印的小程序"这是一个小文本文件"
目前我使用了一个hackish python脚本,但它只是丑陋而且仅限于一个变量名,你能告诉我另一种方法吗?
在C/C++中
在#if 0/ #endifblock 之间放置代码会发生什么?
#if 0
//Code goes here
#endif
Run Code Online (Sandbox Code Playgroud)
代码是否只是被跳过,因此无法执行?
我正在编写一个跨平台的代码,它应该在linux,windows,Mac OS上编译.在窗户上,我必须支持视觉工作室和mingw.
有一些特定于平台的代码,我应该放在#ifdef .. #endif环境中.例如,这里我放置了win32特定代码:
#ifdef WIN32
#include <windows.h>
#endif
Run Code Online (Sandbox Code Playgroud)
但是我如何识别linux和mac OS?我应该使用什么定义名称(或等)?
我试图找出我的代码认为它正在使用的Boost版本.我想做这样的事情:
#error BOOST_VERSION
但预处理器不会扩展BOOST_VERSION.
我知道我可以在程序运行时打印出来,我知道我可以查看预处理器的输出来找到答案.我觉得在编译期间有一种方法可以使用它.
这可能是一种风格问题,但我们的开发团队有一点分歧,我想知道是否有其他人对此事有任何想法......
基本上,我们有一些调试打印语句,我们在正常开发过程中关闭.我个人更喜欢做以下事情:
//---- SomeSourceFile.cpp ----
#define DEBUG_ENABLED (0)
...
SomeFunction()
{
int someVariable = 5;
#if(DEBUG_ENABLED)
printf("Debugging: someVariable == %d", someVariable);
#endif
}
Run Code Online (Sandbox Code Playgroud)
有些团队更喜欢以下内容:
// #define DEBUG_ENABLED
...
SomeFunction()
{
int someVariable = 5;
#ifdef DEBUG_ENABLED
printf("Debugging: someVariable == %d", someVariable);
#endif
}
Run Code Online (Sandbox Code Playgroud)
......哪些方法对你来说听起来更好?为什么?我的感觉是,第一个更安全,因为总有一些东西被定义,并且没有危险它可以破坏其他地方的其他定义.
c-preprocessor ×10
c ×6
c++ ×4
macros ×3
boost ×1
c99 ×1
coding-style ×1
enums ×1
if-statement ×1
include ×1
token ×1
typedef ×1