C:将单词和数字连接到单个标识符运行时
C: Concatenate a word and a number to single identifier runtime
我想将一个单词和一个数字连接到一个标识符,例如使用 ## 预处理器运算符,并用它来索引一个数组。但是,它必须在运行时发生。理想情况下,像这样:
#include <stdio.h>
#define RUNTIME_CONCAT(a,b) //Insert concatenating operation here
int main(){
int foo1[2][1] = {{2}, {5}};
int foo2[2][1] = {{6}, {9}};
/*
By some means acquire number a here
*/
int* print_val = RUNTIME_CONCAT(foo, a)[1];
printf("Value: %d\n", *print_val);
return 0;
}
这可能吗?
如果你想使用宏:
typedef int (*arr21)[2][1];
#define RT(arr, x) (int *)(((arr21 []){&arr ## 1, &arr ## 2})[x])
typedef
只是为了简单起见-否则复合文字的语法将很难阅读。
#define RT(arr, x) (int *)(((arr21 []){&arr ## 1, &arr ## 2})[x])
int main(void){
int foo1[2][1] = {{2}, {5}};
int foo2[2][1] = {{6}, {9}};
volatile int a = 1;
int* print_val = RT(foo, a);
printf("Value: %d\n", *print_val);
return 0;
}
我建议使用一些丑陋的代码,但我认为这正是您要找的。代码后的评论。
/* so.c
*/
#include <stdio.h>
#include <string.h>
int foo1[2][1] = {{2}, {5}};
int foo2[2][3] = {{6, 3, 1}, {9, 7, 5}};
struct array_t {
char *name;
void *ptr;
/* int foo[m][n] */
size_t m, n;
};
struct array_t array[] = {
#define __set(v) {# v, v, \
sizeof(v) / sizeof(v[0]), \
sizeof(v[0]) / sizeof(v[0][0])}
__set(foo1),
__set(foo2),
#undef __set
};
void *getarray(char *base, int idx)
{
char name[100];
snprintf(name, 100, "%s%d", base, idx);
for(int i = 0; i < sizeof(array)/sizeof(struct array_t); i++)
if(!strcmp(array[i].name, name))
return &array[i];
return NULL;
}
int val(struct array_t *array, int m, int n)
{
int *p = array->ptr;
return p[m * array->n + n];
}
void print_array(struct array_t *array)
{
printf("Array: %s[%zu][%zu]\n\n", array->name, array->m, array->n);
for(int m = 0; m < array->m; m++)
for(int n = 0; n < array->n; n++)
printf("%s[%d][%d] = %d\n",
array->name, m, n, val(array, m, n));
printf("\n\n");
}
int main(void)
{
struct array_t *p1, *p2;
p1 = getarray("foo", 1);
p2 = getarray("foo", 2);
print_array(p1);
print_array(p2);
printf("foo2[1][2]: %d\n", val(p2, 1, 2));
return 0;
}
我定义了两个不同大小的数组来尝试制作更通用的东西。
我们定义了一个名为 array_t
的结构,它包含有关我们数组的信息。
我们用数组初始化我们的结构。这是预处理丑的第一点。
__set(v)
依赖于 static
数组来运行(即它不适用于 malloc
数组)。 # v
将变量名转换为字符串。
下一个有趣的位是 sizeof(v) / sizeof(v[0])
,它通过将数组的总大小除以行大小来计算数组的 m
维度。
sizeof(v[0]) / sizeof(v[0][0])
将总行大小除以类型的大小。
getarray
是查找发生的地方。您可以获得一个名称和一个索引,然后 snprintf
将为您创建一个字符串并在我们的全局 table array
.
中循环
val
是一个包装器,可为您提供二维数组给定索引处的元素。
print_array
...好吧,打印数组。
下面显示了如何在运行时将两个项目连接在一起
char myword[] = "the word";
int mynumber = 27;
char *myarray = malloc( 100 ); //note 100 is much larger than needed
sprintf( &myarray[ strlen(myarray) ], "%s%d", myword, mynumber );
以上执行后,myarray[]将包含:
"the word27"
我想将一个单词和一个数字连接到一个标识符,例如使用 ## 预处理器运算符,并用它来索引一个数组。但是,它必须在运行时发生。理想情况下,像这样:
#include <stdio.h>
#define RUNTIME_CONCAT(a,b) //Insert concatenating operation here
int main(){
int foo1[2][1] = {{2}, {5}};
int foo2[2][1] = {{6}, {9}};
/*
By some means acquire number a here
*/
int* print_val = RUNTIME_CONCAT(foo, a)[1];
printf("Value: %d\n", *print_val);
return 0;
}
这可能吗?
如果你想使用宏:
typedef int (*arr21)[2][1];
#define RT(arr, x) (int *)(((arr21 []){&arr ## 1, &arr ## 2})[x])
typedef
只是为了简单起见-否则复合文字的语法将很难阅读。
#define RT(arr, x) (int *)(((arr21 []){&arr ## 1, &arr ## 2})[x])
int main(void){
int foo1[2][1] = {{2}, {5}};
int foo2[2][1] = {{6}, {9}};
volatile int a = 1;
int* print_val = RT(foo, a);
printf("Value: %d\n", *print_val);
return 0;
}
我建议使用一些丑陋的代码,但我认为这正是您要找的。代码后的评论。
/* so.c
*/
#include <stdio.h>
#include <string.h>
int foo1[2][1] = {{2}, {5}};
int foo2[2][3] = {{6, 3, 1}, {9, 7, 5}};
struct array_t {
char *name;
void *ptr;
/* int foo[m][n] */
size_t m, n;
};
struct array_t array[] = {
#define __set(v) {# v, v, \
sizeof(v) / sizeof(v[0]), \
sizeof(v[0]) / sizeof(v[0][0])}
__set(foo1),
__set(foo2),
#undef __set
};
void *getarray(char *base, int idx)
{
char name[100];
snprintf(name, 100, "%s%d", base, idx);
for(int i = 0; i < sizeof(array)/sizeof(struct array_t); i++)
if(!strcmp(array[i].name, name))
return &array[i];
return NULL;
}
int val(struct array_t *array, int m, int n)
{
int *p = array->ptr;
return p[m * array->n + n];
}
void print_array(struct array_t *array)
{
printf("Array: %s[%zu][%zu]\n\n", array->name, array->m, array->n);
for(int m = 0; m < array->m; m++)
for(int n = 0; n < array->n; n++)
printf("%s[%d][%d] = %d\n",
array->name, m, n, val(array, m, n));
printf("\n\n");
}
int main(void)
{
struct array_t *p1, *p2;
p1 = getarray("foo", 1);
p2 = getarray("foo", 2);
print_array(p1);
print_array(p2);
printf("foo2[1][2]: %d\n", val(p2, 1, 2));
return 0;
}
我定义了两个不同大小的数组来尝试制作更通用的东西。
我们定义了一个名为
array_t
的结构,它包含有关我们数组的信息。我们用数组初始化我们的结构。这是预处理丑的第一点。
__set(v)
依赖于static
数组来运行(即它不适用于malloc
数组)。# v
将变量名转换为字符串。下一个有趣的位是
sizeof(v) / sizeof(v[0])
,它通过将数组的总大小除以行大小来计算数组的m
维度。sizeof(v[0]) / sizeof(v[0][0])
将总行大小除以类型的大小。
中循环getarray
是查找发生的地方。您可以获得一个名称和一个索引,然后snprintf
将为您创建一个字符串并在我们的全局 tablearray
.val
是一个包装器,可为您提供二维数组给定索引处的元素。print_array
...好吧,打印数组。
下面显示了如何在运行时将两个项目连接在一起
char myword[] = "the word";
int mynumber = 27;
char *myarray = malloc( 100 ); //note 100 is much larger than needed
sprintf( &myarray[ strlen(myarray) ], "%s%d", myword, mynumber );
以上执行后,myarray[]将包含:
"the word27"