I enjoy it when an experienced coder reviews my stuff. I’m happy with the feedback, and occasionally they toss me a bone. This time it was a rather obscure bone, but I see the point: Avoid using negative array elements.
Somewhere in a code example, I use a variable to set an array’s dimension. This construction is rare, but it’s possible. Specifically, I was admonished for using an unsigned variable to initialize the array. So I got thinking . . .
Consider the source code below, where signed int variable a
is initialized to the value -10. This variable then sets the number of elements in int array values[]
. The program outputs the amount of memory allocated for the array as well as the number of elements.
2021_08_14-Lesson.c
#include <stdio.h> int main() { signed a = -10; int values[a]; printf("Array 'values' occupies %zu bytes of storage\n",sizeof(values)); printf("It contains %ld elements\n",sizeof(values)/sizeof(int)); return(0); }
Here’s a sample run:
Array 'values' occupies 17179869144 bytes of storage
It contains 4294967286 elements
Let me translate: When initialized to -10 elements, the array consumes 17 gigabytes of storage. It contains over 4 billion elements.
My computer has 32GB of RAM, so these are legitimate values. Further, a 12 line C program run at the command prompt grabbed over half the RAM in the system. Impressive.
Obviously, what’s going on is that the compiler is reading the value -10 as unsigned, not signed. For a 32-bit integer value, the unsigned equivalent of -10 is 17179869144 or 0x3FFFFFFD8. I think. I’m not even sure. All I know, is that it’s a Bad Thing to do.
This approach is the only way you can assign negative array elements. If you try to be direct:
int values[-10];
The compiler pukes up an error message; can’t be done!
Still, you can use a variable set array size. If you do so, ensure that you use an unsigned data type. Or, do what I do in these cases: Allocate a pointer instead.
You could argue that this is a compiler bug / “feature”. IMHO it should only accept unsigned types as array indexes. It obviously checks when you use values like -10 so should do the same with variables.
Is this Clang? Does gcc behave in the same way?
It ran the same on the gcc compiler, though I believe gcc just runs clang on my system. The MinGW compiler in Code::Blocks did not like the source code, but it didn’t complain about variable ‘a’ being negative. Weird.