【问题标题】:Is it possible to modify this X-Macro to build a struct, which includes arrays? How?是否可以修改此 X-Macro 以构建包含数组的结构?如何?
【发布时间】:2012-11-13 17:35:04
【问题描述】:

在 SO 上发现了这个非常有用的问答:Is there any way to loop through a struct with elements of different types in C?

但是由于我对整个 X-Macro 的东西还很陌生,所以我想知道,是否以及如何将这个示例用于带有数组的结构 - 像这样:

typedef struct
{    
    uint8    Addr1[SIZEOF_ADDR];
    uint8    Addr2[SIZEOF_ADDR];
    uint8    Addr3[SIZEOF_ADDR];
} TEST;

这是要适应的:

//--- first describe the structure, the fields, their types and how to print them
#define X_FIELDS \
    X(int, field1, "%d") \
    X(int, field2, "%d") \
    X(char, field3, "%c") \
    X(char *, field4, "%s")

//--- define the structure, the X macro will be expanded once per field
typedef struct {
#define X(type, name, format) type name;
    X_FIELDS
#undef X
} mystruct;

我的出发点是这样的,但我很确定,格式必须是别的东西,或者必须被替换:

#define X_FIELDS \
    X(uint8, Addr1, "%02X") \
    X(uint8, Addr2, "%02X") \    
    X(uint8, Addr3, "%02X")

地址类似于 {0x10,0x12,0x0A} - 大小相同。

编辑:

这是我目前如何使用这个结构的一个例子,没有 x-macros:

TEST test =  {{0x16,0xA4,0x3},
              {0x16,0xA4,0x2},
              {0x16,0xA4,0x1}};

printf("%02X",test.addr1[i]);

【问题讨论】:

    标签: c arrays x-macros


    【解决方案1】:

    你有一个合理的开始......

    #include <stdio.h>
    typedef unsigned char uint8;
    enum { SIZEOF_ADDR = 3 };
    
    #define X_FIELDS \
        X(uint8, Addr1, "0x%02X") \
        X(uint8, Addr2, "0x%02X") \
        X(uint8, Addr3, "0x%02X")
    
    //--- define the structure, the X macro will be expanded once per field
    typedef struct {
    #define X(type, name, format) type name[SIZEOF_ADDR];
        X_FIELDS
    #undef X
    } TEST;
    
    extern void iterate1(TEST *test);
    extern void iterate2(TEST *test);
    
    //--- Print the values
    void iterate1(TEST *test)
    {
         const char *pad;
    //--- "iterate" over all the fields of the structure
    #define X(type, name, format) \
             printf("%s is ", #name); \
             pad = "{"; \
             for (size_t i = 0; i < sizeof(test->name); i++) \
             { \
                  printf("%s" format, pad, test->name[i]); \
                  pad = ","; \
             } \
             printf("}\n");
    X_FIELDS
    #undef X
    }
    
    // Alternatively, define a function `print_addr()`
    static void print_addr(const char *format, const uint8 *addr, size_t addrsize)
    {
        char pad = '{';
        for (size_t i = 0; i < addrsize; i++)
        {
            putchar(pad);
            printf(format, addr[i]);
            pad = ',';
        }
        putchar('}');
    }
    
    //--- Print the values using print_addr()
    void iterate2(TEST *test)
    {
        //--- "iterate" over all the fields of the structure
    #define X(type, name, format) \
        printf("%s is ", #name); \
        print_addr(format, test->name, sizeof(test->name)); \
        printf("\n");
        X_FIELDS
    #undef X
    }
    

    (此代码被视为单个文件,已知可以在 Mac OS X 10.7.5 上的 GCC 4.7.1 下干净编译。)

    【讨论】:

    • 嗯,测试了这个,但我遇到了错误——比如 C2078“太多的 inits”,当我在编辑示例中尝试设置 mystruct test 时。 C2109“索引需要数组或指针类型”。后一个是真正困扰我的地方,因为我认为它指出,addr1mystruct 的一个元素,但不是一个数组。我确信我必须在某个地方使用 SIZE_OF_ADDR,所以我猜,仍然没有定义数组 - 或者是吗?
    • 道歉——在 02:00 难以入睡时编写未经测试的代码并不是成功的好方法。上面的代码已经被到处修改,但现在编译时不需要编译器。我没有运行它,但我有一定的信心它会起作用。我不确定 X-Macro 的“格式”部分是否值得拥有它的位置,但我假设确实如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多