我正在阅读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])
然后它说第二种方法的优点是,如果类型发生变化,则不需要更改它。有人可以告诉我最后一行的含义吗?这里谈论什么优势?
如果将来您将keytab
数组更改为与struct key
不同的类型,则必须更改第一个 sizeof 行,因为该类型是显式写入的。第二个 sizeof 行将继续工作,因为它不命名类型,但采用数组元素的任何类型。
对于 1) 代码需要假设我们正在查看类型为struct key
的成员数组。
使用2)代码不需要知道这一点。
出于可维护性的原因,这被认为是 2) 的优点。
考虑几个人在项目上工作,一个人将数组的定义更改为
struct key2 {
char * word;
int count;
int coolness;
} keytab[] = /* ... */
并将struct key
的定义与代码相同。另一个负责具有大小宏定义的代码部分。
然后1)变得错误,但2)保持正确。
因此,1)将需要两个开发人员之间的额外同步,这意味着额外的努力和错误的风险。
">有人能告诉我最后一行的含义吗?">
其实很简单。当您声明某物(任何内容)的数组时,每个元素都是该类型的sizeof
。(例如int array[10] = {0};
声明并初始化一个 10 元素的数组int
) 数组的每个元素都有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 *keytab
或sizeof 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)
进行计算。
有人能告诉我最后一行的含义吗?
获取类型为struct key
的数组元素的实际数量
这里谈论什么优势?
除了不明确依赖于某种类型的优点之外,
编译器可以使用实际定义对宏进行更多优化。 与sizeof(var)
相比,sizeof(type)
优化得更好。