在 C 中使用带有类型的粘贴运算符`##`

Use of pasting operator `##` with types in C

是否可以为 C 预处理器定义一个以数组为参数并扩展为 <type of array elements>_string 的宏?例如,如果 x 在整数数组中,则使用参数 x 调用的宏应扩展为 int_string.

我试过

#define TypePaste(array) typeof(array[0])##_string

但它会扩展到 )_string

即使对 ## 操作数使用多级间接寻址,宏也无法正确展开。

这不可能。在翻译阶段(预处理阶段)宏被扩展和标记被连接,编译器(此时,预处理器)还没有type 因此不可能生成类型。

不是很清楚您要解决的问题,但鉴于您的评论:

the macro should expand to the name of an existing function. I'd like to define a function <type>_string for every existing type and then use the macro to select the right function according to the type of the array given.

那么你可以使用 C11 _Generic 关键字:

#include <stdio.h>

void int_string (size_t size, int array[size])
{
  printf("I am %s, do stuff here.\n", __func__);
}

void float_string (size_t size, float array[size])
{
  printf("I am %s, do stuff here.\n", __func__);
}

#define TypePaste(array)          \ 
  _Generic( array,                \
            int:   int_string,    \
            float: float_string ) \
  (sizeof(array)/sizeof(*array), array) // function parameters



int main()
{
  int   i_arr[5];
  float f_arr[3];

  TypePaste(i_arr);
  TypePaste(f_arr);
}

输出:

I am int_string, do stuff here.
I am float_string, do stuff here.

注意:这假设传递的参数是一个 local/file 作用域分配数组。如果传递指针,则没有类型安全,程序将失败。

C11 的 _Generic 类型选择是 "proper" 做你想做的事的方式。还有其他依赖于平台的解决方案,很难。

如果您正在使用 gcc – 您没有明说,但您已经使用了 gcc 的扩展 typeof – 您可以使用 gcc 的 statement expresions and nested functions 为 [=15= 创建一个比较函数] 现场:

double a[5] = {8.4, 8.1, 9.3, 12.2, 5.2};

qsort(a, 5, sizeof(*a), ({
    int cmp(const void *p, const void *q) {
        const typeof(a[0]) *pp = p;
        const typeof(a[0]) *qq = q;

        return (*pp < *qq) ? -1 : (*pp > *qq);
    }
    cmp;
}));

这将创建一个函数并return它的地址。 (复合表达式的最后一条语句是它的值。局部变量的范围是语句表达式,但嵌套函数不是在堆栈上创建的,因此 return 指向该函数的指针是安全的。)

对于原始类型,如果您想根据比较运算符 <> 进行排序,您可以将其转换为宏:

#define COMPARE(ARRAY)({             \
        int cmp(const void *p, const void *q) {         \
            const typeof(ARRAY[0]) *pp = p;             \
            const typeof(ARRAY[0]) *qq = q;             \
            return (*pp < *qq) ? -1 : (*pp > *qq);      \
        }                                               \
        cmp;                                            \
    })

qsort(a, 5, sizeof(*a), COMPARE(a));

甚至:

#define SORT(ARRAY, N)                                  \
    qsort(ARRAY, N, sizeof(*ARRAY), COMPARE(ARRAY))

SORT(a, 5);

那不是标准 C,所以如果你需要平台之间的兼容性,这是不可能的。