Tag: c preprocessor

正确的定义NULL和NULL_POINTER的方法?

据我所知, C定义NULL如下: #define NULL ( (void *) 0) 那么,我们应该如何定义NULL_POINTER ? 我在我的程序中将它定义为相同并且它有效,但我认为这只是一个巧合: #define NULL_POINTER ( (void *) 0) 如果有的话,逻辑定义是什么?

Varargs`ELEM`宏用于C

我想知道是否一般使用ELEM比较宏,其中: (v == a || v == b) 可以替换为: ELEM(v, a, b) 当然这可以用宏来完成, #define ELEM(v, a, b) (((v) == (a)) || ((v) == (b))) 然而,您最终需要定义多个带参数计数的宏。 使用一个简单的python脚本我想出了这个: #define ELEM2(v, a, b) \ (((v) == (a)) || ((v) == (b))) #define ELEM3(v, a, b, c) \ (ELEM2(v, a, b) || ((v) == (c))) #define ELEM4(v, a, b, […]

基于参数的C预处理器宏专业化

是否有可能为一个特定的参数值以不同的方式扩展一个宏,对所有其他参数的扩展方式不同? 假设我定义了一个当前用户: #define CURRENT_USER john_smith 我想要做的是有一个宏,如果用户传递匹配CURRENT_USER将扩展不同。 请注意,我不知道所有可能的用户先验。 最基本的案例: #define IS_CURRENT_USER(user) \ /* this is not valid preprocessor macro */ \ #if user == CURRENT_USER \ 1 \ #else \ 0 \ #endif 像宏一样,依赖于用户名的每个其他宏都可以按照以下方式完成: #define SOME_USER_SPECIFIC_MACRO(user) SOME_USER_SPECIFIC_MACRO_SWITCH_1(IS_CURRENT_USER(user)) #define SOME_USER_SPECIFIC_MACRO_SWITCH_1(switch) SOME_USER_SPECIFIC_MACRO_SWITCH_2(switch) // expand switch … #define SOME_USER_SPECIFIC_MACRO_SWITCH_2(switch) SOME_USER_SPECIFIC_MACRO_##switch // … and select specific case #define SOME_USER_SPECIFIC_MACRO_0 … […]

使用#ifdefs和#define可选择将函数调用转换为注释

有可能做这样的事情 #ifdef SOMETHING #define foo // #else #define foo MyFunction #endif 我们的想法是,如果定义了SOMETHING,那么对foo(…)的调用将成为注释(或者不会被评估或编译的内容),否则它将成为对MyFunction的调用。 我见过__noop,但我不相信我可以使用它。 编辑(S): 我不认为我真的可以在这里使用宏,因为MyFunction采用可变数量的参数。 另外,我想这样做,所以不评估参数! (所以做一些事情,比如评论MyFunction的主体并没有真正给我我需要的东西,因为参数仍将被评估)

C #include filename中的连接字符串

当#including文件名(在C中)时,是否可以从另一个宏连接字符串。 例如, 我有, #define AA 10 #define BB 20 这些参数随程序运行而变化 该文件包括: #include “file_10_20” // this changes correspondingly ie file_AA_BB 是否有可能以某种方式拥有#include “file_AA_BB”类的东西? 我用谷歌搜索发现双磅操作符可以连接字符串,但无法找到一种方法。 任何帮助,将不胜感激。

为什么我不能在预处理器条件下使用sizeof?

我知道sizeof是一个运算符,它在编译时被计算为整数常量。 但它似乎不能在#if预处理器指令中使用,如: #if 4 == sizeof(int) typedef int Int32; #endif (cygwin-gcc 3.4.4以及Visual C ++ 6.0报告编译错误) 为什么不允许这样的使用?

轻松“反转”C预处理器宏的集合

我有很多预处理器宏定义,如下所示: #define FOO 1 #define BAR 2 #define BAZ 3 在实际应用中,每个定义对应于解释器虚拟机中的指令。 这些宏在编号方面也不是连续的,以便为将来的指令留出空间; 可能有#define FOO 41 ,然后下一个是#define BAR 64 。 我现在正在为这个虚拟机开发一个调试器,需要有效地“反转”这些预制宏。 换句话说,我需要一个获取数字并返回宏名称的函数,例如2的输入返回”BAR” 。 当然,我可以自己创建一个使用switch的function: const char* instruction_by_id(int id) { switch (id) { case FOO: return “FOO”; case BAR: return “BAR”; case BAZ: return “BAZ”; default: return “???”; } } 但是,这将是一个难以维护的噩梦,因为重命名,删除或添加指令也需要修改此function。 是否有另一个宏可以用来为我创建这样的函数,还是有其他方法? 如果没有,是否可以创建宏来执行此任务? 我在Windows 10上使用gcc 6.3。

C预处理器#和##运算符

C99标准文档在与##预处理运算符相关的部分中有以下示例: 在以下片段中: #define hash_hash # ## # #define mkstr(a) # a #define in_between(a) mkstr(a) #define join(c, d) in_between(c hash_hash d) char p[] = join(x, y); // equivalent to // char p[] = “x ## y”; 扩张在不同阶段产生: join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y) “x ## y” 换句话说,扩展hash_hash会产生一个新的令牌,由两个相邻的尖锐符号组成,但这个新令牌不是##运算符。 我不明白为什么hash_hash的替换产生##而不是“##”或“#”“#”。 在双哈希播放之前和之后单个哈希的角色是什么? 任何回复都非常感谢。

头文件只包含在整个程序中一次?

我知道这是一个常见的问题,但我仍然无法完全理解它。 在从多个不同的源文件和头文件生成的C或C ++程序中,当使用标头保护时,每个头文件是否只包含在整个代码中一次? 之前有人告诉我,头文件(带有包含警卫)只能在一个翻译单元中包含一次,但在整个代码中会多次包含。 这是真的? 如果它在整个代码中只被包含一次,当一个文件希望包含它并且预处理器检测到它已经被包含时,那个希望使用它的文件如何知道它之前包含的代码中的位置?

头文件中的变量定义

我对C和编译过程的基本知识最近变得生疏。 我试图找出以下问题的答案,但我无法连接编译,链接和预处理阶段基础知识。 快速搜索谷歌也没有多大帮助。 所以,我决定来到最终的知识来源:) 我知道:不应该在.h文件中定义变量。 可以在那里宣布它们。 原因:因为头文件可能包含在多个位置,因此重新定义变量多次(链接器给出错误)。 可能的解决方法:在头文件中使用header-guard并在其中定义变量。 它真的是一个解决方案:不。因为标题保护是用于预处理阶段。 那就是告诉编译器这部分已经包含在内并且不再包含它。 但是我们的多重定义错误出现在链接器部分 – 在编译之后。 整件事让我对预处理和链接的工作方式感到困惑。 如果已经定义了头部保护符号,我认为预处理将不包括代码。 在那种情况下,不应该解决变量问题的多重定义吗? 这些预处理指令会在标题保护下重新定义编码过程,但链接器仍会获得符号的多个定义,会发生什么?