sizeof 运算符如何用于结构

How sizeof operator works for a structure

我正在阅读 K&R。在一个示例中,它定义了一个结构数组:

struct key {
char * word;
int count;
} keytab[] = {
   "auto", 0,
   "break", 0,
   /*more members*/
   "while", 0
};

然后计算数组的大小,它使用两种方法:

1) #define NKEYS (sizeof keytab/ sizeof(struct key))
2) #define NKEYS (sizeof keytab/ sizeof keytab[0])

然后说第二种方式的好处是类型改变了也不需要改变。谁能告诉我这最后一行的意思?这里说的优势是什么?

"Can someone tell me the meaning of this last line?"

真的很简单。当你声明一个东西(任何东西)的数组时,每个元素都是 sizeof 那个类型。 (例如 int array[10] = {0}; 声明并初始化 int 的 10 元素数组)数组的每个元素都有 sizeof (int).

您可以使用 array[x] 访问每个元素(其中 x 是 0-9)。任何元素,例如array[0] 是一个 int。 (正如 *array 是对第一个元素的引用——其中 array[0] 只是指针表示法中的 *(array + 0),当然,它只是 *(array)*array, 因为括号是不必要的)。

回到struct的数组大小。 sizeof keytab 给出数组中的总字节数。 sizeof keytab[0] 给出每个元素中的字节数。因此 sizeof keytab / sizeof keytab[0] 是数组中元素的数量。和写sizeof keytab / sizeof *keytabsizeof keytab / sizeof (struct key)一样。

为什么?因为 sizeof keytab[0] 就是 sizeof (struct key)。但是如果你根据 sizeof (struct key) 调整元素数量然后改变类型,那么你所有带有 sizeof (struct key) 的代码都会出错,但是如果你使用 sizeof keytab[0] 调整大小,你的代码将继续计算出正确数量的元素,因为您是根据 sizeof "an element" 而不是 sizeof (an arbitrary type name).

计算的

对于 1),代码需要假设我们正在查看 struct key.
类型的成员数组 对于 2),代码不需要知道这一点。

出于可维护性原因,这被认为是 2) 的优势。
考虑几个从事该项目的人,其中一个将数组的定义更改为

struct key2 {    
    char * word;
    int count;
    int coolness;    
} keytab[] = /* ... */

并在其他地方分隔 struct key 的定义,与您的代码相同。另一个负责size宏定义的代码部分

然后 1) 变得错误,但 2) 保持正确。
因此 1) 需要两个开发人员之间的额外同步,这意味着额外的工作和出错的风险。

如果将来您将 keytab 数组更改为与 struct key 不同的类型,则必须更改第一个 sizeof 行,因为类型已明确写入那里。第二行 sizeof 将继续工作,因为它没有命名类型,而是采用数组元素的任何类型。

Can someone tell me the meaning of this last line?

获取类型为struct key

的数组元素的实际个数

What advantage is being talked about here?

除了不明确依赖于某种类型的优点外,

编译器可以使用实际定义对宏进行更多优化。 sizeof(var)sizeof(type) 相比优化得更好。