I'm trying to understand why sizeof(a)/sizeof(t)
is inferior for getting the length of an array to sizeof(a)/sizeof(a[0])
if just as it's possible to have different types, my elements could also be of different lengths. so what makes dividing by the element size uniform?
2 Answers
The difference between sizeof(a)/sizeof(t)
and sizeof(a)/sizeof(a[0])
is that for the first one you need to supply two pieces of information (the array name and the type of its elements) while the second one needs only a single piece of information (the array name).
The more pieces of information you need to provide, the more chance there is that a mistake is made. To make matters worse, if a mistake is made in the element type of the array, there is no safety net to catch that mistake. You will just get incorrect results.
And a mistake does not mean only when the code initially gets written, but also when later on changes are mode to it.
Suppose you start out with
int arr[N];
…
array_length = sizeof(arr)/sizeof(int);
later on you find that int
isn't the right type, because you also need to store fractional numbers, so you change it to double
, but you forget the sizeof expression:
double arr[N];
…
array_length = sizeof(arr)/sizeof(int);
Now suddenly, the value of array_length
is no longer correct. If you had written it as array_length = sizeof(arr)/sizeof(arr[0]);
, then that mistake could not have happened.
-
It could be argued that a name change is far more likely than a type change. But a name change is an automated refactoring. Even if done by hand, a mistake would produce a compiler error. So I'm strongly in the
a[0]
camp. Code should welcome refactoring. Apr 28, 2020 at 8:54 -
@candied_orange I personally prefer trimming it down to
sizeof a / sizeof *a
as I dislike senseless verbosity, not that it changes anything much. Apr 29, 2020 at 6:09 -
@Deduplicator I’ve heard that debased as well. Some like it short. Some think the long one makes it clearer that you’re looking at the size of an element. Personally I wish the whole thing was hidden behind a good abstraction. Apr 29, 2020 at 6:13
Also consider the pros/cons from a reviewer point of view.
size_t a_size1 = sizeof(a)/sizeof(int);
size_t a_size2 = sizeof(a)/sizeof(a[0]);
The type definition of a
may not be near these lines of code, perhaps in a .h file.
To check either line of code, we need to know if a
is in fact an array and not a pointer. This is a binary consideration that is usually understood in review - not much cost.
Yet sizeof(int)
obliges another check: does the type match? For the original coder, this is not much of issue and so may appear inconsequential. Yet for a reviewer who has cursory knowledge of the code, it is a tedious check.
This is a similar concern of @Bart van Ingen Schenau good answer, yet I wanted to emphasize the increased negative impact on reviewers.
a
andt
come from. Give multiple examples. In particular, explain whata
andt
would be, if someone passes in: (1) an array typedef, (2) an array instance, (3) a pointer. Please remember that most people do not have the same "K.N.King" book as yours. If your question depends on something from that book, be sure to explain it here.