我知道我正试图在腿上射击自己;)然而,它将允许我使其余(大量)代码更小,更易读.
是否有任何棘手的方法在另一个预处理器宏内部创建预处理器宏?
这是一个例子,我在寻找什么.我的真实场景更复杂
// That's what I want to do and surely C++ doesn't like it.
#define MACROCREATER(B) #define MACRO##B B+B
void foo()
{
MACROCREATOR(5) // This should create new macro (#define MACRO5 5+5)
int a = MACRO5; // this will use new macro
}
Run Code Online (Sandbox Code Playgroud) C风格的宏名称是否与标识符具有相同的命名规则?在编译器升级之后,它现在为遗留应用程序发出此警告:
warning #3649-D: white space is required between the macro name "CHAR_" and its replacement text
#define CHAR_& 38
Run Code Online (Sandbox Code Playgroud)
这行代码定义了&符号的ASCII值常量.
#define DOL_SN 36
#define PERCENT 37
#define CHAR_& 38
#define RT_SING 39
#define LF_PAR 40
Run Code Online (Sandbox Code Playgroud)
我假设这个定义(实际上没有被任何代码引用,据我所知)是错误的,应该改为像"CHAR_AMPERSAND"这样的东西?
我写了一个可变参数模板,它接受可变数量的char
参数,即
template <char... Chars>
struct Foo;
Run Code Online (Sandbox Code Playgroud)
我只是想知道是否有任何宏技巧允许我使用类似于以下语法实例化它:
Foo<"abc">
Run Code Online (Sandbox Code Playgroud)
要么
Foo<SOME_MACRO("abc")>
Run Code Online (Sandbox Code Playgroud)
要么
Foo<SOME_MACRO(abc)>
Run Code Online (Sandbox Code Playgroud)
等等
基本上,任何阻止你单独写字符的东西,就像这样
Foo<'a', 'b', 'c'>
Run Code Online (Sandbox Code Playgroud)
这对我来说不是一个大问题,因为它只是一个玩具程序,但我想我还是会问.
出于某种原因,我需要暂时禁用头文件中的某些宏,这#undef MACRONAME
将使代码编译,但它将取消现有的宏.
有没有一种方法可以禁用它?
我应该提到你并不真正了解宏的值,而且我正在寻找交叉编译器解决方案(至少应该在GCC和MSVC中工作).
在此站点上看到,代码显示了使用括号中的波浪号进行的宏调用:
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
// ^^^
Run Code Online (Sandbox Code Playgroud)
它是什么意思/做什么?我怀疑它只是一个空洞的争论,但我不确定.它是否特定于C(99),就像__VA_ARGS__
C99特有的并且存在于C++中一样?
请注意,因为这是一个问题的地狱;-)
我想在C中使用模板函数进行泛型集合操作(如search,foreach等),同时保持编译器静态类型检查.当你使用像这个例子中的简单回调时,这是相当简单的:
#define MAKE_FOREACH(TYPE)\
void foreach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)) {\
for(int i = 0; i < n; i++) {\
f(array[i]);\
}\
}
Run Code Online (Sandbox Code Playgroud)
所以你可以这样做:
MAKE_FOREACH(int)
MAKE_FOREACH(float)
void intcallback(int x){
printf("got %d\n", x);
}
void floatcallback(float x){
printf("got %f\n", x);
}
int main(){
int[5] iarray = {1,2,3,4,5};
float[5] farray = {1.0,2.0,3.0,4.0,5.0};
foreach_int(iarray, 5, intcallback);
foreach_float(farray, 5, floatcallback);
}
Run Code Online (Sandbox Code Playgroud)
如果我想用返回类型实现回调,例如创建一个"map"函数,我可以这样做:
#define MAKE_MAP(TYPE, RTYPE)\
RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE)) {\
RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);\
for(int i = 0; i < …
Run Code Online (Sandbox Code Playgroud) 我遇到了一个问题 - 我需要使用宏值作为字符串和整数.
#define RECORDS_PER_PAGE 10
/*... */
#define REQUEST_RECORDS \
"SELECT Fields FROM Table WHERE Conditions" \
" OFFSET %d * " #RECORDS_PER_PAGE \
" LIMIT " #RECORDS_PER_PAGE ";"
char result_buffer[RECORDS_PER_PAGE][MAX_RECORD_LEN];
/* ...and some more uses of RECORDS_PER_PAGE, elsewhere... */
Run Code Online (Sandbox Code Playgroud)
这失败了一条关于"stray#"的消息,即使它有效,我想我会得到字符串化的宏名称,而不是值.当然,我可以将值提供给最终的方法("LIMIT %d ", page*RECORDS_PER_PAGE
),但它既不漂亮也不高效.当我希望预处理器不以特殊方式处理字符串并且像普通代码一样处理它们的内容时,就像这样.就目前而言,我对它进行了解决,#define RECORDS_PER_PAGE_TXT "10"
但可以理解的是,我对它并不满意.
怎么做对吗?
对于debugbuilds,我通常使用Clang,因为它更好地格式化警告和错误,并使它更容易跟踪它们并修复它们.
但最近在添加了具有可变参数的宏之后,Clang告诉我以下内容(来自虚拟项目):
main.cpp:5:20: warning: named variadic macros are a GNU extension [-Wvariadic-macros]
#define stuff3(args...) stuff_i(args)
Run Code Online (Sandbox Code Playgroud)
我知道macroname(args...)
在各种编译器中编译很好,包括Visualstudio,Sunstudio,当然还有GCC.但是为了确保clang是正确的,我尝试了另外两种扩展可变参数的方法:
1号:
#define stuff1(...) stuff_i(...)
Run Code Online (Sandbox Code Playgroud)
2号:
#define stuff2(...) stuff_i(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
我都收到这条消息:
main.cpp:3:16: warning: variadic macros were introduced in C99 [-Wvariadic-macros]
Run Code Online (Sandbox Code Playgroud)
...这让我想知道Variadic宏是否实际上是C++标准的一部分(当然我知道预处理器是独立解释的)?
[9.5]为什么我应该使用内联函数而不是普通的旧#define宏?
因为
#define
宏在四种不同的方面是邪恶的:邪恶的#1,邪恶的#2,邪恶的#3和邪恶的#4.有时你应该使用它们,但它们仍然是邪恶的.与#define
宏不同,内联函数避免了臭名昭着的宏错误,因为内联函数总是只评估每个参数一次.换句话说,调用内联函数在语义上就像调用常规函数一样,只是更快:Run Code Online (Sandbox Code Playgroud)// A macro that returns the absolute value of i #define unsafe(i) \ ( (i) >= 0 ? (i) : -(i) ) // An inline function that returns the absolute value of i inline int safe(int i) { return i >= 0 ? i : -i; } int f(); void userCode(int x) { int ans; ans = unsafe(x++); // Error! x is incremented twice ans = unsafe(f()); // Danger! f() is …
我需要实现一些使用不同数字数组的方法.通常,我会使用泛型来完成这项工作,但由于C不提供它们,我现在正试图使用宏来模拟它们.
这是我正在尝试做的一个例子:
#ifndef TYPE
#define TYPE int
#endif
TYPE get_minimum_##TYPE (TYPE * nums, int len){
TYPE min = nums[0];
for (int i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译.clang错误消息:
错误:预期';' 在顶级声明者之后
有没有办法在C中这样做?或者我需要手动为每种类型实现这个吗?