Reputation: 307
I am reading K&R. In an example it defines an array of structures as:
struct key {
char * word;
int count;
} keytab[] = {
"auto", 0,
"break", 0,
/*more members*/
"while", 0
};
Then to calculate the size of the array, it uses two approaches:
1) #define NKEYS (sizeof keytab/ sizeof(struct key))
2) #define NKEYS (sizeof keytab/ sizeof keytab[0])
Then it says that the second approach has the advantage that it does not need to be changed if the type changes. Can someone tell me the meaning of this last line? What advantage is being talked about here?
Upvotes: 1
Views: 202
Reputation: 12174
Can someone tell me the meaning of this last line?
Getting the actual number of array elements with type struct key
What advantage is being talked about here?
Aside from the advantage of not being explicitly dependent to a certain type,
compilers can do more optimization for macros using actual definitions. sizeof(var)
is much better optimized compared to sizeof(type)
.
Upvotes: 0
Reputation: 84521
"Can someone tell me the meaning of this last line?"
It's quite simple really. When you declare an array of something (anything), each element is the sizeof
that type. (e.g. int array[10] = {0};
declares and initializes a 10-element array of int
) Each element of the array has sizeof (int)
.
You can access each element with array[x]
(where x is 0-9
). Any element, e.g. array[0]
is an int
. (just as *array
is a reference to the first element -- where array[0]
is simply *(array + 0)
in pointer notation, which, of course, is just *(array)
or *array
, since the parenthesis are then unnecessary).
Back to the size of the array of struct
. sizeof keytab
gives the total number of bytes in the array. sizeof keytab[0]
gives the number of bytes in each element. Therefore sizeof keytab / sizeof keytab[0]
is the number of element in the array. It is the same as writing sizeof keytab / sizeof *keytab
or sizeof keytab / sizeof (struct key)
.
Why? Because sizeof keytab[0]
is just the sizeof (struct key)
. But if you size the number of elements based on sizeof (struct key)
and then change the type, all your code with sizeof (struct key)
will be wrong, but if you size with sizeof keytab[0]
, your code will continue to have the correct number of elements calculated because you calculate based on the sizeof "an element"
not sizeof (an arbitrary type name)
.
Upvotes: 2
Reputation: 4881
If in future you change the keytab
array to be of a different type than struct key
, then the first sizeof line has to be changed because the type was written there explicitly. The second sizeof line will remain working because it does not name the type, but takes whatever type of the array element is.
Upvotes: 4
Reputation: 26703
With 1) the code needs to assume that we are looking at an array of members of type struct key
.
With 2) the code does not need to know that.
For maintainability reasons, this is considered an advantage of 2).
Consider several people working on the project, one changes the definition of the array to
struct key2 {
char * word;
int count;
int coolness;
} keytab[] = /* ... */
and separates the definition of struct key
elsewhere, identically to your code. The other one is in charge of the code part with the size macro definition.
Then 1) becomes wrong, but 2) stays correct.
Hence 1) would required additional synchronisation between two developers, which means additional effort and risk of errors.
Upvotes: 2