使用粘贴运算符`##`和C中的类型

时间:2016-01-12 08:18:52

标签: c macros typeof

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

我试过

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

但它会扩展为)_string

即使对##操作数使用多级间接,宏也不能正确扩展。

3 个答案:

答案 0 :(得分:6)

那是不可能的。在转换阶段(预处理阶段),其中宏被扩展并且标记被连接,编译器(此时,预处理器)还没有类型的概念因此不可能生成类型。

答案 1 :(得分:3)

您要解决的问题并不是很清楚,但请注意:

  

宏应扩展为现有函数的名称。我想为每个现有类型定义一个函数<type>_string,然后根据给定数组的类型使用宏来选择正确的函数。

然后您可以使用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.

注意:这假定传递的参数是本地/文件范围分配的数组。如果传递指针,则没有类型安全,程序将失败。

答案 2 :(得分:0)

C11的_Generic类型选择是“正确”的方式来做你想要的。还有其他依赖于平台的解决方案,很难。

如果你正在使用gcc - 你没有这么说,但是你已经使用了gcc的扩展名typeof - 你可以使用gcc的statement expresionsnested functions创建一个比较函数qsort当场:

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;
}));

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

对于基本类型,您希望根据比较运算符<>进行排序,您可以将其转换为宏:

#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,所以如果你需要平台之间的兼容性,这是不可能的。