【问题标题】:How to calculate the size of a data member in a structure?如何计算结构中数据成员的大小?
【发布时间】:2020-06-17 09:26:36
【问题描述】:

我无法理解size_1 变量如何计算数据成员名称的大小。有人能解释一下(((struct cheese_msgbuf*)0)->name);这条线的含义和作用吗?

#include<stdio.h>
struct cheese_msgbuf {
    long mtype;
    char name[20];
};

int main() {
    /* calculate the size of the data to send: */
    struct cheese_msgbuf mbuf;
    int size;
    int size_1;

    size = sizeof(mbuf.name);
    printf("Using just sizeof operator: %d\n", size);

    /* Or, without a declared variable: */
    size_1 = sizeof(((struct cheese_msgbuf*)0)->name);
    printf("Using pointer: %d\n", size_1);
}

【问题讨论】:

  • 这条语句(struct cheese_msgbuf*)0 将空指针转换为你的结构类型(struct cheese_msgbuf)。
  • sizeof 在编译期间而不是在运行时解决。因此,当您告诉编译器在地址 0 处有一个 cheese_msgbuf 类型的结构时,编译器会信任您。

标签: c struct sizeof


【解决方案1】:

您可能知道,sizeof 是一个返回特定 C 符号大小的运算符。它要么需要变量名,要么需要类型;如果变量名是数组名,则返回整个数组的字节数。

但是没有 “直接” 方法来获取结构字段的大小,所以这就是您找到的技巧(我不得不说您的代码非常不言自明):

/* Or, without a declared variable: */
size_1 = sizeof(((struct cheese_msgbuf*)0)->name);
  1. 我们构建一个指向定义字段的结构的指针:((struct cheese_msgbuf*)0)。我们只是投地址0;我们不需要它是一个有效的地址,我们只需要告诉编译器将它解释为指向(struct cheese_msgbuf*) 的指针
  2. 我们访问我们需要的字段:char 数组name。我们只是访问该字段,就像我们有一个“真实”变量时访问它一样,例如var-&gt;name
    在这种情况下,我们只访问((struct cheese_msgbuf*)0)-&gt;name
  3. 我们将它传递给sizeof 运算符:sizeof(((struct cheese_msgbuf*)0)-&gt;name)。它将被解析为20

【讨论】:

    【解决方案2】:

    如果您有一个指向struct cheese_msgbuf 的指针p,您可以使用sizeof p-&gt;name 获得name 成员的大小。

    这段代码没有这样的指针,因此它通过将0 转换为struct cheese_msgbuf * 类型来构造一个。结果是一个空指针。

    在执行的代码中,当p 是空指针时,评估p-&gt;name 是不合适的。在许多 C 实现中,它会生成一个异常,并且它不是由 C 标准定义的。

    但是,sizeof 运算符在这种情况下不会计算其操作数。它是一种编译时操作,它根据操作数的类型而不是对操作数的任何实际求值来生成操作数的大小。由于表达式((struct cheese_msgbuf *) 0)-&gt;name 的名义类型是char [20],所以表达式sizeof ((struct cheese_msgbuf *) 0)-&gt;name 产生20。

    (如果sizeof的操作数是变长数组,则计算操作数。否则,不计算操作数。)

    【讨论】:

      【解决方案3】:

      转换 NULL 指针

      你可以看看这段代码 sn-p(来自你上面的代码):

      /* Or, without a declared variable: */
      size_1 = sizeof(((struct cheese_msgbuf*)0)->name);
      printf("Using pointer: %d\n", size_1);
      

      这个技巧在c 编程中被称为强制转换 NULL ptr。我们可以查看null 指针,例如:(void*)0,同样我们可以将它们转换为我们自己定义的类型,例如您的struct cheese_msgbuf 类型。

      编译器帮你获取sizeofstruct cheese_msgbuf数据成员name, 如下:

      struct cheese_msgbuf* compiler_temp_pointer = ((struct cheese_msgbuf*)0);
      size_t size = sizeof(compiler_temp_pointer->name);
      

      希望这对你来说清楚

      【讨论】:

      • 那么,struct cheese_msgbuf* compiler_temp_pointer = ((struct cheese_msgbuf*)0); 等价于 struct cheese_msgbuf* compiler_temp_pointer = NULL;?
      猜你喜欢
      • 2019-05-08
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 2021-04-08
      • 2014-02-09
      • 2014-10-04
      相关资源
      最近更新 更多