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

https://godbolt.org/z/rjWMrzda9

我建议使用一些丑陋的代码,但我认为这正是您要找的。代码后的评论。

/* 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;
}
  1. 我定义了两个不同大小的数组来尝试制作更通用的东西。

  2. 我们定义了一个名为 array_t 的结构,它包含有关我们数组的信息。

  3. 我们用数组初始化我们的结构。这是预处理丑的第一点。

  4. __set(v) 依赖于 static 数组来运行(即它不适用于 malloc 数组)。 # v 将变量名转换为字符串。

  5. 下一个有趣的位是 sizeof(v) / sizeof(v[0]),它通过将数组的总大小除以行大小来计算数组的 m 维度。

  6. sizeof(v[0]) / sizeof(v[0][0]) 将总行大小除以类型的大小。

  7. getarray 是查找发生的地方。您可以获得一个名称和一个索引,然后 snprintf 将为您创建一个字符串并在我们的全局 table array.

    中循环
  8. val 是一个包装器,可为您提供二维数组给定索引处的元素。

  9. 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"