Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 根据宏的内容定义宏_C_Macros - Fatal编程技术网

C 根据宏的内容定义宏

C 根据宏的内容定义宏,c,macros,C,Macros,是否可以根据宏的内容定义宏 例如: #define SET(key,value) #define key value SET(myKey,"value") int main(){ char str[] = myKey; printf("%s",str); } 会导致 int main(){ char str[] = "value"; printf("%s",str); } 经过预处理后 我为什么要这样做?因为我很好奇;) 不,不可能在另一个宏中定义宏。预处理器在编

是否可以根据宏的内容定义宏

例如:

#define SET(key,value) #define key value

SET(myKey,"value")

int main(){
   char str[] = myKey;
   printf("%s",str);
}
会导致

int main(){
   char str[] = "value";
   printf("%s",str);
}
经过预处理后


我为什么要这样做?因为我很好奇;)

不,不可能在另一个宏中定义宏。

预处理器在编译器之前只迭代一次。您的建议需要不确定的迭代次数。

宏是一种简单的文本替换。从宏生成新的预处理器指令需要预处理器从替换开始就继续进行预处理。但是,标准定义的预处理将在替换之后继续进行

从流的角度来看,这是有意义的,将未处理的代码视为输入流,将已处理(和替换)的代码视为输出流。宏替换可以具有任意长度,这意味着对于从开始的预处理,必须在要再次处理的输入流的开头插入任意数量的字符


当在替换后继续处理时,输入只需在一次运行中处理,无需任何插入或缓冲,因为所有内容都直接进入输出。

尽管无法使用宏定义另一个宏,但这取决于您想要实现的目标,通过让宏定义常量,可以使用宏有效地实现同样的目标。例如,我有一个广泛的c宏库,用于定义目标c常量字符串和键值

下面是我的一些标题中的一些代码片段

// use defineStringsIn_X_File to define a NSString constant to a literal value.
// usage (direct)   : defineStringsIn_X_File(constname,value);

#define defineStringsIn_h_File(constname,value)   extern NSString * const constname; 
#define defineStringsIn_m_File(constname,value)   NSString * const constname = value; 


// use defineKeysIn_X_File when the value is the same as the key. 
// eg myKeyname has the value @"myKeyname"
// usage (direct)   : defineKeysIn_X_File(keyname);
// usage (indirect) : myKeyDefiner(defineKeysIn_X_File);
#define defineKeysIn_h_File(key)  defineStringsIn_h_File(key,key) 
#define defineKeysIn_m_File(key)  defineStringsIn_m_File(key,@#key) 



// use defineKeyValuesIn_X_File when the value is completely unrelated to the key - ie you supply a quoted value.
// eg myKeyname has the value @"keyvalue"
// usage: defineKeyValuesIn_X_File(keyname,@"keyvalue");
// usage (indirect) : myKeyDefiner(defineKeyValuesIn_X_File);
#define defineKeyValuesIn_h_File(key,value)   defineStringsIn_h_File(key,value)  
#define defineKeyValuesIn_m_File(key,value)   defineStringsIn_m_File(key,value) 



// use definePrefixedKeys_in_X_File when the last part of the keyname is the same as the value.
// eg myPrefixed_keyname has the value @"keyname"
// usage (direct)   : definePrefixedKeys_in_X_File(prefix_,keyname);
// usage (indirect) : myKeyDefiner(definePrefixedKeys_in_X_File);

#define definePrefixedKeys_in_h_File_2(prefix,key) defineKeyValuesIn_h_File(prefix##key,@#key) 
#define definePrefixedKeys_in_m_File_2(prefix,key) defineKeyValuesIn_m_File(prefix##key,@#key) 

#define definePrefixedKeys_in_h_File_3(prefix,key,NSObject) definePrefixedKeys_in_h_File_2(prefix,key)
#define definePrefixedKeys_in_m_File_3(prefix,key,NSObject) definePrefixedKeys_in_m_File_2(prefix,key)

#define definePrefixedKeys_in_h_File(...) VARARG(definePrefixedKeys_in_h_File_, __VA_ARGS__)
#define definePrefixedKeys_in_m_File(...) VARARG(definePrefixedKeys_in_m_File_, __VA_ARGS__)




// use definePrefixedKeyValues_in_X_File when the value has no relation to the keyname, but the keyname has a common prefixe
// eg myPrefixed_keyname has the value @"bollocks"
// usage: definePrefixedKeyValues_in_X_File(prefix_,keyname,@"bollocks");
// usage (indirect) : myKeyDefiner(definePrefixedKeyValues_in_X_File);
#define definePrefixedKeyValues_in_h_File(prefix,key,value) defineKeyValuesIn_h_File(prefix##key,value) 
#define definePrefixedKeyValues_in_m_File(prefix,key,value) defineKeyValuesIn_m_File(prefix##key,value) 







#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(X,##__VA_ARGS__, 11, 10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define VARARG_IMPL2(base, count, ...) base##count(__VA_ARGS__)
#define VARARG_IMPL(base, count, ...) VARARG_IMPL2(base, count, __VA_ARGS__) 
#define VARARG(base, ...) VARARG_IMPL(base, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
以及调用它的使用示例:

#define sw_Logging_defineKeys(defineKeyValue) \
/** start of key list for sw_Logging_ **/\
/**/defineKeyValue(sw_Logging_,log)\
/**/defineKeyValue(sw_Logging_,time)\
/**/defineKeyValue(sw_Logging_,message)\
/**/defineKeyValue(sw_Logging_,object)\
/**/defineKeyValue(sw_Logging_,findCallStack)\
/**/defineKeyValue(sw_Logging_,debugging)\
/**/defineKeyValue(sw_Logging_,callStackSymbols)\
/**/defineKeyValue(sw_Logging_,callStackReturnAddresses)\
/** end of key list for sw_Logging_ **/
sw_Logging_defineKeys(definePrefixedKeys_in_h_File);
最后一部分可能有点难以理解。 sw_Logging_defineKeys()宏定义了一个列表,该列表以宏的名称作为参数(defineKeyValue),然后用于调用执行实际定义过程的宏。也就是说,对于列表中的每个项目,传入的宏名称用于定义上下文(“标题”或“实现”,如“h”或“m”文件,如果您了解目标c文件扩展名),而这用于目标c时,它只是简单的旧c宏,用于可能从未设想过的“更高用途”。:-)

不可以-#在宏的替换列表中,表示引用下一个标记。这更像是一个拼写问题,而不是任何逻辑难题:)

(如果您需要在代码中使用这种解决方案,那么使用宏的方法和技巧就不多了,但您需要具体说明您需要的用例——您的示例可以通过定义:#define mykey“value”来实现)

这里它来自ansi C99标准

6.10.3.2#操作员

约束条件

1替换列表中的每个预处理令牌,用于 类似宏的函数后面应跟随一个参数作为下一个参数 正在预处理替换列表中的令牌。语义2如果,在 替换列表中,参数前面紧跟着# 预处理标记,两者都由单个字符串替换 文本预处理标记,其中包含 预处理对应参数的标记序列。每个 参数的预处理标记之间出现空白 成为字符串文字中的单个空格字符。 第一个预处理标记之前和最后一个预处理标记之后的空白 已删除构成参数的预处理标记。否则 参数中每个预处理标记的原始拼写为 保留在字符串文字中,特殊处理除外 用于生成字符串文字和字符常量的拼写: 在字符的每个“和\字符之前插入\字符 常量或字符串文字(包括分隔字符), 除非是实现定义的\字符是否为 插入通用字符名开头的\字符之前。 如果替换结果不是有效的字符串 文字,行为未定义。字符串文字 与空参数对应的是“”。评价顺序# 和##运算符未指定


编辑你的片段,让它有机会编译;并尝试编译它。会发生什么?我也很好奇。@PeteWilson试图编译上面的代码,我得到了
错误:“#”后面没有宏参数
,因为“我为什么要这样做?”:-)的错误+1。预处理器不会简单地确定宏一次。预处理器允许您多次#取消定义"和#定义宏。它会在整个处理过程中更改和编辑宏,没有任何东西会阻止它在宏内部编辑这些规则。预处理器所做的是按一定顺序“检查所有文件并替换一些字符串”。有一个命令的事实允许它拥有内存和#undef#ifdef等。。。但是,要将替换的字符串作为宏获取,需要递归。请提供一个示例。我同意如果您想替换内部
#define
之前的文本,则需要递归,但如果代码从上一点开始生效,则似乎没有问题。我不明白您想要什么示例,然而,在我看来,这似乎很简单:这要么是标准支持的,然后它应该递归,要么是不支持的,然后它根本就不支持——这似乎是这样的,因为在宏定义中不允许使用
。。举个例子可以帮助我理解是什么阻止了嵌套
定义
的出现在标准中实施。这似乎不是一个递归问题,您能否提供一个
c
代码示例来说明递归是必要的。