如何循环遍历结构变量的每个成员?

时间:2021-07-21 11:24:47

标签: c struct reflection

此代码只是我正在寻找的简化版本。通常我想知道如何访问任何类型的变量,所以也许我可以输入 horse[6] 来访问 int,以及 horse[7] 来访问 char .

#include<stdio.h>

struct horse_s{
    int age;
    int height;
    int width;
    int weight;
}horse;

struct horse_s horse_default = {1, 2, 3, 4};

int main(){
    int i;
    int a = sizeof(struct horse); //I want this to return the amount of members in the struct
    for(i = 0; i<a; i++){
        horse_1[i] = horse_default[i] + 2; //I want this to access the i-th member of the struct variable
    }

    printf("Horse age: %d\n", horse.age);
    printf("Horse height: %d\n", horse.height);
    printf("Horse width: %d\n", horse.width);
    printf("Horse weight: %d\n", horse.weight);

    return 0;
}

2 个答案:

答案 0 :(得分:4)

不可能,C语言是没有reflection的语言。

您可以编写一个单独的程序来处理您的程序的源代码并提取您想要的信息并修改您的源文件或生成一些带有所需信息的单独的 C 源代码,然后将所有结果提供给 C 编译器.

您可以使用 offsetof 或大型 switch case 手动编写和维护每个字段的访问器。这样的实现看起来像:

#include <assert.h>
#include <stddef.h>
#include <stdlib.h>

struct horse_s {
    int age;
    int height;
    int width;
    int weight;
};

static const size_t HORSE_MEMB_CNT = 4;

int *horse_get_memb(struct horse_s *t, size_t idx) {
     // using offsetof
     const size_t offsets[] = {
         offsetof(struct horse_s, age),
         offsetof(struct horse_s, height),
         offsetof(struct horse_s, width),
         offsetof(struct horse_s, weight),
     };
     static_assert(sizeof(offsets)/sizeof(*offsets) == HORSE_MEMB_CNT, "");
     assert(idx < HORSE_MEMB_CNT);
     return (int*)((char*)t + offsets[idx]);

     // using switch case
     switch (idx) {
     case 0: return &t->age;
     case 1: return &t->height;
     case 2: return &t->width;
     case 3: return &t->weight;
     default: assert(0);
     }
     return 0;
}

int main() {
    struct horse_s horse;
    *horse_get_memb(&horse, 2) = 42; // assigns to width
}

你的编译器很可能会一个接一个地分配结构成员。在这种情况下,您可以直接使用它,但它违反了一些语言规则, 应该使用并且可能不起作用。

static_assert(offsetof(struct horse_s, age) == 0, "");
static_assert(offsetof(struct horse_s, height) == sizeof(int) * 1, "");
static_assert(offsetof(struct horse_s, width) == sizeof(int) * 2, "");
static_assert(offsetof(struct horse_s, weight) == sizeof(int) * 3, "");
int *horsearr = (int*)&horse;
horsearr[2] = 42; // assigns to width

无论如何,如果您想使用存储在某个结构实例中的一些默认值来初始化一个结构,那么只需初始化或分配该结构即可。

 const struct horse_s horse_default = { some defaults };
 int main() {
     struct horse_s horse = horse_default;
 }

答案 1 :(得分:2)

你不能在 C 中做到这一点。它是一种相对低级的语言。 sizeof 以字节为单位返回结构的大小,[] 用于指针解引用。

做与您想要的类似的事情的唯一方法是使用数组。您可以使用索引的常量来模拟命名成员。