有没有办法在GCC中的C宏中将参数用作前缀

有没有办法在GCC中的C宏中将参数用作前缀,c,macros,C,Macros,我正在尝试用C语言编写一些模板: 我需要创建一个2d向量结构,其中包含一些函数来使用它们,我需要将它们用于int、unsigned int、float、double甚至其他类型,这些类型都支持基本的数学功能 我可以为每种类型编写所有代码。如果我在其中一个文件中写了一个bug,我可能会忘记修复所有其他文件中的bug。我以前在C++中做过,我只是用了模板,但是现在我想在C(C11)…没有 所以我看了一下宏,我发现可以使用##标记直接使用宏传递的参数 以下是我尝试过的一些代码: #define DEC

我正在尝试用C语言编写一些模板: 我需要创建一个2d向量结构,其中包含一些函数来使用它们,我需要将它们用于int、unsigned int、float、double甚至其他类型,这些类型都支持基本的数学功能

我可以为每种类型编写所有代码。如果我在其中一个文件中写了一个bug,我可能会忘记修复所有其他文件中的bug。我以前在C++中做过,我只是用了模板,但是现在我想在C(C11)…没有

所以我看了一下宏,我发现可以使用##标记直接使用宏传递的参数

以下是我尝试过的一些代码:

#define DECLARE_VEC2(N, T) \
  typedef struct { T x, y;} N; \
  inline N *##N_new() { return malloc(sizeof(N));}

DECLARE_VEC2(vec2i, int);
DECLARE_VEC2(vec2f, float);
DECLARE_VEC2(vec2d, double);
它不起作用。##N没有被vec2i/vec2f/vec2d替换,而是保留为##N,甚至只是N。编译器不会接受它,当我在文件上使用-E标志运行gcc时,我看到预处理器确实没有替换它

但是,如果我在##N和#u new之间添加一个空格,预处理器会替换它,但该空格也在那里,这显然会在编译时产生问题

但是,如果我将函数名更改为new###N,它不仅预处理良好,而且工作正常

但我不想要后者! 我创建的所有结构的功能都是这样的:typename_function(),我不想因为这个愚蠢的问题而改变它

所以,问题是:有没有办法解决这个问题

注意:我还尝试过向包含下划线的宏添加额外参数,甚至在添加下划线的宏中声明宏,但它们都遇到了相同的问题:需要某种分隔符,使预处理器理解名称在下划线或其后面的任何内容之前结束

编辑:奇怪的是,当使用诸如##N####u new()之类的东西时,预处理器会很好地替换名称,但随后不会接受它,并出现以下错误:

error: pasting "*" and "vec2i" does not give a valid preprocessing token
   inline N * ##N##_new() { return malloc(sizeof(N));}
尽管生成的代码似乎是正确的(gcc-E):

##
不是前缀运算符,它是中缀运算符-一种类似于
+
的二进制串联运算符。所以你可以这样使用它:

#define DECLARE_VEC2(N, T) \
  typedef struct { T x, y;} N; \
  inline N * N##_new() { return malloc(sizeof(N));}

注意,<>代码>α→< /COD>的空白被忽略,所以如果你认为它更可读,你也可以做同样的效果:

#define DECLARE_VEC2(N, T) \
  typedef struct { T x, y;} N; \
  inline N * N ## _new() { return malloc(sizeof(N));}

这也应该解释为什么你会得到错误“没有给出一个有效的预处理令牌”:你实际上是在试图将
*
int
连接成一个令牌。

内联N*N###u new(void)
哇,好吧,这在我从中学到的书中没有很好地解释。它现在似乎预处理/编译很好(尽管我得到了一个链接器错误,关于函数vec2f_new的未定义引用,你知道为什么吗)?@scipie关于这本书:也许他们不知怎么把它与
#
(转换为字符串)预处理器操作符混在一起了,这确实是前缀?关于链接器错误:不幸的是,我的主要语言是C++,我不熟悉C中的代码> >内联< /Cult>函数的精确语义(因为这是两种语言显著不同的领域之一)。谢谢…我通过添加static关键字解决了这个问题。现在,这些函数被反复添加到每个包含头文件的文件中,作为该文件的唯一函数并进行内联优化。C99中
inline
本身的语义很难解释,而且几乎从来都不是您想要的<代码>静态内联更像是C++中的代码>内联如何运行,更具意义。
#define DECLARE_VEC2(N, T) \
  typedef struct { T x, y;} N; \
  inline N * N ## _new() { return malloc(sizeof(N));}