使用 C 预处理器给出数组值
use C pre-processor to give an array values
我有一些代码需要将数组设置为一些(动态)值。根据某些因素,数组的内容应该有不同的来源。这不能自动完成,需要手动写出来。
array[0] = x;
array[1] = y;
array[2] = z;
....
..
我希望它有点自动,所以我的第一个方法是:
void set_array(char *array, int_num args, ...){
va_list valist;
va_start(valist, num_args);
for(int i=0; i < num_args; i++)
array[i] = va_arg(valist, char);
va_end(valist);
}
调用 set_array(array, x, y, z)
将导致 array[0] = x
、array[1] = y
等。
但是速度很重要,所以我想摆脱函数调用和动态内存分配。
我的第二种方法是:
#define SET1(i, A, B) A[i] = B;
#define SET2(i, A, B, C) A[i] = B; SET1(i+1, A, C)
#define SET3(i, A, B, C, D) A[i] = B; SET2(i+1, A, C, D)
#define SET4(i, A, B, C, D, E) A[i] = B; SET3(i+1, A, C, D, E)
#define SET5(i, A, B, C, D, E, F) A[i] = B; SET4(i+1, A, C, D, E, F)
#define SET6(i, A, B, C, D, E, F, G) A[i] = B; SET5(i+1, A, C, D, E, F, G)
#define SET7(i, A, B, C, D, E, F, G, I) A[i] = B; SET6(i+1, A, C, D, E, F, G, I)
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
#define SET(...) GET_MACRO(0, __VA_ARGS__, SET7, SET6, SET5, SET4, SET3, SET2, SET1)(0, __VA_ARGS__)
调用 SET(array, x, y, z)
将导致 array[0] = x
、array[1] = y
等。
此方法会产生更快的代码,但需要我为每个参数数量编写一个宏。有没有使用宏的方法来规避这个?
如果我没理解错的话,你想要一种方法来分配给一个数组,它具有可用于数组初始化的语法便利…
array = {x, y, z}
但这是在运行时发生的赋值,而不是初始化。
您可以通过分配给临时数组并立即复制来完成。任何半途而废的编译器都会优化副本。
{
int tmp = {x, y, z};
memcpy(array, tmp, sizeof(tmp));
}
你可以把它打包成一个宏。省略 C99 中的 static_assert
(这是 C11 中的新功能)。
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int array[42];
size_t used_size;
#define SET_ARRAY(...) \
do { \
int const SET_ARRAY_tmp[] = {__VA_ARGS__}; \
static_assert(sizeof(SET_ARRAY_tmp) <= sizeof(array), \
"too many values in assignment to array"); \
memcpy(array, SET_ARRAY_tmp, sizeof(SET_ARRAY_tmp)); \
used_size = sizeof(SET_ARRAY_tmp) / sizeof(SET_ARRAY_tmp[0]); \
} while (0)
void f(int fourth) {
SET_ARRAY(123, 456, 789, fourth);
}
请注意,元素的数量必须在编译时已知。如果您只知道在运行时要复制的元素数量,您将需要一种不同的方法,尽管由于您必须从 某处 中提取元素,因此它可能只是一个 memcpy
.
我有一些代码需要将数组设置为一些(动态)值。根据某些因素,数组的内容应该有不同的来源。这不能自动完成,需要手动写出来。
array[0] = x;
array[1] = y;
array[2] = z;
....
..
我希望它有点自动,所以我的第一个方法是:
void set_array(char *array, int_num args, ...){
va_list valist;
va_start(valist, num_args);
for(int i=0; i < num_args; i++)
array[i] = va_arg(valist, char);
va_end(valist);
}
调用 set_array(array, x, y, z)
将导致 array[0] = x
、array[1] = y
等。
但是速度很重要,所以我想摆脱函数调用和动态内存分配。
我的第二种方法是:
#define SET1(i, A, B) A[i] = B;
#define SET2(i, A, B, C) A[i] = B; SET1(i+1, A, C)
#define SET3(i, A, B, C, D) A[i] = B; SET2(i+1, A, C, D)
#define SET4(i, A, B, C, D, E) A[i] = B; SET3(i+1, A, C, D, E)
#define SET5(i, A, B, C, D, E, F) A[i] = B; SET4(i+1, A, C, D, E, F)
#define SET6(i, A, B, C, D, E, F, G) A[i] = B; SET5(i+1, A, C, D, E, F, G)
#define SET7(i, A, B, C, D, E, F, G, I) A[i] = B; SET6(i+1, A, C, D, E, F, G, I)
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
#define SET(...) GET_MACRO(0, __VA_ARGS__, SET7, SET6, SET5, SET4, SET3, SET2, SET1)(0, __VA_ARGS__)
调用 SET(array, x, y, z)
将导致 array[0] = x
、array[1] = y
等。
此方法会产生更快的代码,但需要我为每个参数数量编写一个宏。有没有使用宏的方法来规避这个?
如果我没理解错的话,你想要一种方法来分配给一个数组,它具有可用于数组初始化的语法便利…
array = {x, y, z}
但这是在运行时发生的赋值,而不是初始化。
您可以通过分配给临时数组并立即复制来完成。任何半途而废的编译器都会优化副本。
{
int tmp = {x, y, z};
memcpy(array, tmp, sizeof(tmp));
}
你可以把它打包成一个宏。省略 C99 中的 static_assert
(这是 C11 中的新功能)。
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int array[42];
size_t used_size;
#define SET_ARRAY(...) \
do { \
int const SET_ARRAY_tmp[] = {__VA_ARGS__}; \
static_assert(sizeof(SET_ARRAY_tmp) <= sizeof(array), \
"too many values in assignment to array"); \
memcpy(array, SET_ARRAY_tmp, sizeof(SET_ARRAY_tmp)); \
used_size = sizeof(SET_ARRAY_tmp) / sizeof(SET_ARRAY_tmp[0]); \
} while (0)
void f(int fourth) {
SET_ARRAY(123, 456, 789, fourth);
}
请注意,元素的数量必须在编译时已知。如果您只知道在运行时要复制的元素数量,您将需要一种不同的方法,尽管由于您必须从 某处 中提取元素,因此它可能只是一个 memcpy
.