标签: c-preprocessor

在C/C++预处理器中,单个磅/井号(#)在其自己的行上的目的是什么?

我一直在查看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都应该正确解析它.在整个代码中使用随机井号/井号的影响/副作用是什么?

c c++ boost c-preprocessor

144
推荐指数
3
解决办法
1万
查看次数

如何使用C预处理器连接两次并扩展宏,如"arg ## _ ## MACRO"?

我正在尝试编写一个程序,其中一些函数的名称依赖于某个宏变量的值,宏如下:

#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并单独列出所有情况,但我想知道是否有一个聪明的方法来做到这一点.

c concatenation token c-preprocessor

141
推荐指数
3
解决办法
7万
查看次数

GCC的标准替代## __ VA_ARGS__技巧?

C99中的可变参数宏存在一个众所周知的 空args 问题.

例:

#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 c99 c-preprocessor variadic-macros

141
推荐指数
6
解决办法
7万
查看次数

我应该使用#define,enum还是const?

在我正在研究的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++ enums bit-manipulation c-preprocessor

123
推荐指数
6
解决办法
6万
查看次数

"#include"C程序中的文本文件为char []

有没有办法在编译时将整个文本文件作为字符串包含在C程序中?

就像是:

获取一个在stdout上打印的小程序"这是一个小文本文件"

目前我使用了一个hackish python脚本,但它只是丑陋而且仅限于一个变量名,你能告诉我另一种方法吗?

c include c-preprocessor

123
推荐指数
7
解决办法
6万
查看次数

#if 0 ..... #endif块到底是做什么用的?

C/C++中

#if 0/ #endifblock 之间放置代码会发生什么?

#if 0

//Code goes here

#endif
Run Code Online (Sandbox Code Playgroud)

代码是否只是被跳过,因此无法执行?

c-preprocessor

115
推荐指数
6
解决办法
9万
查看次数

113
推荐指数
5
解决办法
7万
查看次数

如何从预处理器宏中识别平台/编译器?

我正在编写一个跨平台的代码,它应该在linux,windows,Mac OS上编译.在窗户上,我必须支持视觉工作室和mingw.

有一些特定于平台的代码,我应该放在#ifdef .. #endif环境中.例如,这里我放置了win32特定代码:

#ifdef WIN32
#include <windows.h>
#endif
Run Code Online (Sandbox Code Playgroud)

但是我如何识别linux和mac OS?我应该使用什么定义名称(或等)?

c++ macros cross-platform c-preprocessor

112
推荐指数
4
解决办法
10万
查看次数

如何在编译时显示#define的值?

我试图找出我的代码认为它正在使用的Boost版本.我想做这样的事情:

#error BOOST_VERSION

但预处理器不会扩展BOOST_VERSION.

我知道我可以在程序运行时打印出来,我知道我可以查看预处理器的输出来找到答案.我觉得在编译期间有一种方法可以使用它.

macros c-preprocessor boost-preprocessor

110
推荐指数
7
解决办法
10万
查看次数

#ifdef vs #if - 作为启用/禁用特定代码段编译的方法更好/更安全?

这可能是一种风格问题,但我们的开发团队有一点分歧,我想知道是否有其他人对此事有任何想法......

基本上,我们有一些调试打印语句,我们在正常开发过程中关闭.我个人更喜欢做以下事情:

//---- 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 c++ if-statement coding-style c-preprocessor

109
推荐指数
9
解决办法
9万
查看次数