C预处理器宏扩展连接

C预处理器宏扩展连接,c,macros,C,Macros,假设我想使用C预处理器来定义一个函数族,其中只有一个参数类型发生了变化。以带参数的分配函数为例: #include <stdint.h> #include <stdio.h> #define type_vector(t) \ t * t##vector(int32_t nl, int32_t nh) \ {

假设我想使用C预处理器来定义一个函数族,其中只有一个参数类型发生了变化。以带参数的分配函数为例:

#include <stdint.h>
#include <stdio.h>

#define type_vector(t)                                              \
t * t##vector(int32_t nl, int32_t nh)                               \
{                                                                   \
    t * v = NULL; /* malloc(...) */                                 \
    return v;                                                       \
}

type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)

int main() {
    int32_t * p;
    p = int32_tvector(10, 12);
    return 0;
}
但是,这不会编译,导致以下错误:

error: pasting ")" and "vector" does not give a valid preprocessing token
 t * sn(t)##vector(int32_t nl, int32_t nh)                           \
据我所知,问题在于“)”和“#”并列。 因此,我做了以下工作:

#define sn_int8_t(f)   i8##f
#define sn_int32_t(f)  i32##f
#define sn_int64_t(f)  i64##f

#define sn2(t,f)       sn_##t(f)

#define type_vector(t)                                              \
t * sn2(t,vector)(int32_t nl, int32_t nh)                           \
{                                                                   \
    t * v = NULL; /* malloc(...) */                                 \
    return v;                                                       \
}

type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)

int main() {
    int32_t * p;
    p = i32vector(10, 12);
    return 0;
}
这又起作用了

现在,假设我想在函数名中添加一个前缀,例如“remote\uux”

简单地说

#define type_vector(t)                                              \
t * remote_##sn2(t,vector)(int32_t nl, int32_t nh)                  \
{                                                                   \
    t * v = NULL; /* malloc(...) */                                 \
    return v;                                                       \
}
不起作用,因为sn2没有扩展。所以我试了一下:

#include <stdint.h>
#include <stdio.h>

#define sn_int8_t(f)   i8##f
#define sn_int32_t(f)  i32##f
#define sn_int64_t(f)  i64##f

#define sn2(t,f)       sn_##t(f)

#define short_name(n,t,f) n##_##sn2(t,f)

#define remote_type_vector(t)                                       \
t * short_name(remote,t,vector)(int32_t nl, int32_t nh)             \
{                                                                   \
    t * v = NULL;                                                   \
    return v;                                                       \
}

remote_type_vector(int8_t)
remote_type_vector(int32_t)
remote_type_vector(int64_t)

int main() {
    int32_t * p;
    p = remote_i32vector(10, 12);
    return 0;
}
有办法吗


<>注释:我不想使用C++模板。

这是一个统一的解决方案,应该满足所有的需要:

#define sn_int8_t(p,s)  p##i8##s
#define sn_int32_t(p,s) p##i32##s
#define sn_int64_t(p,s) p##i64##s

#define sn2(t,p,s)       sn_##t(p,s)

#define type_vector(t)                                              \
t * sn2(t,,vector)(int32_t nl, int32_t nh)                          \
{                                                                   \
    t * v = NULL; /* malloc(...) */                                 \
    return v;                                                       \
}

#define remote_type_vector(t)                                       \
t * sn2(t,remote,vector)(int32_t nl, int32_t nh)                    \
{                                                                   \
    t * v = NULL;                                                   \
    return v;                                                       \
}

type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)

remote_type_vector(int8_t)
remote_type_vector(int32_t)
remote_type_vector(int64_t)

有些人声称这种魔法是邪恶的……使用灵活的数组成员会使思考变得简单得多。关于其余的:TL;DR.Provide a.“我不想在宏函数声明中添加第二个参数”-为什么不?并不是说你经常调用宏。第二个参数还允许您使用具有复合名称的类型(
char*
struct thing
),而不使用
typedef
。如果您不知道,可以使用
gcc-E
检查预处理器的输出,我想所有C编译器都有这样做的选项。@EugeneSh。这样的黑魔法在史前时代就被禁止了。。至少在18世纪之前,巫术、巫术和巨魔术的实践者通常会被逐出教会或被绞死、抽签和分尸。
int32_t * remote_sn2(int32_t,vector)
#define sn_int8_t(p,s)  p##i8##s
#define sn_int32_t(p,s) p##i32##s
#define sn_int64_t(p,s) p##i64##s

#define sn2(t,p,s)       sn_##t(p,s)

#define type_vector(t)                                              \
t * sn2(t,,vector)(int32_t nl, int32_t nh)                          \
{                                                                   \
    t * v = NULL; /* malloc(...) */                                 \
    return v;                                                       \
}

#define remote_type_vector(t)                                       \
t * sn2(t,remote,vector)(int32_t nl, int32_t nh)                    \
{                                                                   \
    t * v = NULL;                                                   \
    return v;                                                       \
}

type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)

remote_type_vector(int8_t)
remote_type_vector(int32_t)
remote_type_vector(int64_t)