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