【问题标题】:x macro prints wrong offsetof() informationx 宏打印错误的 offsetof() 信息
【发布时间】:2017-07-20 02:56:05
【问题描述】:

我对在 X 宏中使用 offsetof() 时出现明显错误感到困惑。下面的代码显示了一个相当简单的结构的两个示例,一个显式定义,另一个使用 X 宏定义。然后将两个结构中每个结构字段的偏移量打印到屏幕上。正如您在下面的 cmets 中看到的,用 X 宏定义的结构中的 c 字段显示了不正确的偏移量。

我相信这是一个打印问题。有人能解释一下这个谜吗?

#include <stdio.h>
#include <stdlib.h>

const char fmt[] = "%-5s 0x%04x(%05d)\n";

#define i(s, f) \
    #f, \
    offsetof(s, f), \
    offsetof(s, f)

int main(void)
{
    /**********************************
    METHOD1 - CORRECTLY PRINTS

        a     0x0000(00000)
        b     0x0004(00004)
        c     0x0008(00008)
        d     0x0030(00048)

    **********************************/
    typedef struct {
        uint32_t a;
        uint32_t b;
        uint32_t c[10];
        uint32_t d;
    } struct1;

    printf(fmt, i(struct1, a));
    printf(fmt, i(struct1, b));
    printf(fmt, i(struct1, c));
    printf(fmt, i(struct1, d));

    printf("\n");

    /**********************************
    METHOD2 - PRINTS WRONG INFO

        a     0x0000(00000)
        b     0x0004(00004)
        c[10] 0x0030(00048)  <== WRONG
        d     0x0030(00048)

    **********************************/

    #define FIELDS \
        X(uint32_t, a,     "") \
        X(uint32_t, b,     "") \
        X(uint32_t, c[10], "") \
        X(uint32_t, d,     "") \

    typedef struct {
    #define X(type, name, descr) type name;
        FIELDS
    #undef X
    } struct2;

    #define X(type, name, descr) printf(fmt, i(struct2, name));
        FIELDS
    #undef X

    return 0;
}

【问题讨论】:

  • 您使用了错误的格式说明符,导致未定义的行为。 %x 用于无符号整数,%d 用于int,但offsetof 产生size_t
  • 你的 X-macro 最终输出 offsetof(struct2, c[10]),这与第一个示例不同的是 offsetof(struct1, c)
  • 感谢@M.M 澄清问题所在。你能想出一种方法来重新定义我的 x 宏以产生所需的结果吗?
  • 也许你可以让 X 宏分别拥有声明和普通名称,例如X(uint32_t c[10], c, "")
  • @rici 是的,我的立场是正确的。将删除评论。

标签: c macros printf c-preprocessor offsetof


【解决方案1】:

在第二个 X 宏中:

  #define X(type, name, descr) printf(fmt, i(struct2, name));
  FIELDS

这扩展为:

printf(fmt, "a", offsetof(struct2, a), offsetof(struct2, a));
printf(fmt, "b", offsetof(struct2, b), offsetof(struct2, b));
printf(fmt, "c[10]", offsetof(struct2, c[10]), offsetof(struct2, c[10]));
printf(fmt, "d", offsetof(struct2, d), offsetof(struct2, d));

offsetof(struct2, c[10])显然和offsetof(struct2, c)不一样。

【讨论】:

    【解决方案2】:

    在上述cmets的帮助下,我想出了答案。对于数组的结构元素,我需要有不同的 X 宏定义。

    #include <stdio.h>
    #include <stdlib.h>
    
    const char fmt[] = "%-5s 0x%04x(%05d)\n";
    
    #define i(s, f) \
        #f, \
        offsetof(s, f), \
        offsetof(s, f)
    
    int main(void)
    {
        /**********************************
           METHOD1 - CORRECTLY PRINTS
    
               a     0x0000(00000)
               b     0x0004(00004)
               c     0x0008(00008)
               d     0x0030(00048)
    
         **********************************/
        typedef struct {
            uint32_t a;
            uint32_t b;
            uint32_t c[10];
            uint32_t d;
        } struct1;
    
        printf(fmt, i(struct1, a));
        printf(fmt, i(struct1, b));
        printf(fmt, i(struct1, c));
        printf(fmt, i(struct1, d));
    
        printf("\n");
    
        /**********************************
           METHOD2 - PRINTS WRONG INFO
    
               a     0x0000(00000)
               b     0x0004(00004)
               c     0x0008(00008) <== CORRECT
               d     0x0030(00048)
    
         **********************************/
    
        #define FIELDS \
             X(uint32_t, a,     "") \
             X(uint32_t, b,     "") \
            AX(uint32_t, c, 10, "") \
             X(uint32_t, d,     "") \
    
        typedef struct {
        #define  X(type, name, descr)       type name;
        #define AX(type, name, size, descr) type name[size];
            FIELDS
        #undef  X
        #undef AX
        } struct2;
    
        #define  X(type, name, descr)       printf(fmt, i(struct2, name));
        #define AX(type, name, size, descr) printf(fmt, i(struct2, name));
            FIELDS
        #undef  X
        #undef AX
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 2019-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多