Arrays are weird and sizeof()
may not always work how you expect. An array is not the same as a pointer and sometimes you will come unstuck. There are several C-based solutions to this problem depending on your specific needs, each with it’s role to play.
So we have some array, let’s say s
- and we want to determine the size in C. A pretty standard thing to do. So let’s do it:
0001 int main(){ 0002 char s[] = {"Hello World!"}; 0003 printf("Size of 's' is %u\n", sizeof(s)); 0004 }
This then outputs Size of 's' is 13
, so all is good. But we don’t plan to use it here, we plan to use it in some function, like so:
0005 void test(char* s){ 0006 printf("Size of 's' is %u\n", sizeof(s)); 0007 } 0008 0009 int main(){ 0010 char s[] = {"Hello World!"}; 0011 test(s); 0012 }
The output is now Size of 's' is 8
. Hang on a second! What? sizeof()
now fails to return the correct size because I passed it to a function? That “8” seems familiar some how… It doesn’t feel like a coincidence that it is the same size as a pointer…
This isn’t the first time I’ve run into this, my previous solution was to supply the length as an additional parameter, curl up into a ball and forget the problem exists. But not this time. This time I will grapple with the oddity (because I’m putting off doing more important work).
Okay, so apparently it is some kind of array pointer decay. I never formally got taught C or C++, so this was interesting to learn of indeed. I was under the impression that things wouldn’t do strange things in C, this is why I use it after all. But it turns out, this is not so much the case. Why do you do this to me?!
It turns out an array is a special thing, you can declare:
0013 char s[] = {"Hello World!"};
And this is a proper array. But if I pass this to a function normally (by pointer), information about size is lost.
It turns out there are several representations of the array:
char* a
- By pointer.char a[]
- By value.char (&a)[t]
Without going into details that others have, only functions that receive arrays by reference can use sizeof()
to determine array size.
So here we have a comparison of potential solutions (including the ones that don’t work):
0014 void test_ptr(char* a){ 0015 printf("(ptr) Size of 'a' is %u\n", sizeof(a)); 0016 } 0017 0018 void test_val(char a[]){ 0019 printf("(val) Size of 'a' is %u\n", sizeof(a)); 0020 } 0021 0022 struct Structure{ 0023 char* a; 0024 unsigned int len; 0025 }; 0026 0027 void test_str(struct Structure s){ 0028 printf("(str) Size of 'a' is %u\n", s.len); 0029 } 0030 0031 void test_cnt(char* a){ 0032 int len = 0; 0033 while(a[len++] != '\0'); 0034 printf("(cnt) Size of 'a' is %u\n", len); 0035 } 0036 0037 void test_par(char* a, int len){ 0038 printf("(par) Size of 'a' is %u\n", len); 0039 } 0040 0041 int main(){ 0042 char s[] = {"Hello World!"}; 0043 printf("Size of 's' is %u\n", sizeof(s)); 0044 // by pointer 0045 test_ptr(s); 0046 // by value 0047 test_val(s); 0048 // structure method 0049 struct Structure z; 0050 z.a = s; 0051 z.len = sizeof(s); 0052 test_str(z); 0053 // count method 0054 test_cnt(s); 0055 // param method 0056 test_par(s, sizeof(s)); 0057 }
This results in:
0058 Size of 's' is 13 0059 (ptr) Size of 'a' is 8 0060 (val) Size of 'a' is 8 0061 (str) Size of 'a' is 13 0062 (cnt) Size of 'a' is 13 0063 (par) Size of 'a' is 13
The counting method (test_cnt()
) is really only appropriate for simple array types that you know their terminating byte. This is not reliable and is quite slow.
The structure method (test_str()
) is fine enough, but it could add complexity to your code, when all you really want is a simple array. Inventing data types is all fine and dandy until your code grows and is used by others.
The parameter method (test_par()
) is probably ideal, as long as the number of parameters you have is quite small. This is the one I have been using for years as a workaround anyway.