All your question shows is that the concept of "magic numbers" and rules against using "magic numbers" in your program are completely and utterly idiotic. Rules against magic numbers are poor approximations, by people who don't understand what they're doing, of a much saner rule against hard-coding in multiple places values which must agree or which depend on one another. For instance, this code is perfectly reasonable, as long as the buffer length does not need to match anything else in the program or real world:
char buf[100];
snprintf(buf, sizeof buf, ...);
But this code is highly bad:
char buf[100];
snprintf(buf, 100, ...);
Of course in the real world there probably is something you want the buffer size to match, for instance the max number of digits needed to print an integer of some particular size. In this case, you might want something like:
char buf[3*sizeof(int)+3];
snprintf(buf, sizeof buf, ...);
And if you consider CHAR_BIT
to be variable then you might want to replace 3 with a formula in terms of CHAR_BIT
. In any case, the constants appearing in the expression are not "evil magic numbers".
In your example, if the dimension of the array is dependent upon some other variable, then all three of your array definitions are bad practice. But if the dimension 4 is fundamental to what you're doing, I don't see anything wrong with it.
Of course, what you're doing can sometimes change during the lifetime of code, but that's what documentation is for. Code cannot be expected to handle ever possible future change-of-purpose without some level of modification, and as long as you documented what its original purpose and contracts are, it should not be hard for someone changing those to find the parts of the code that need changing.