4

Let us consider int array[] = {2,33,4,56,7,8}; //case A

if sizeof() checked '\0' as end of char[] array! what does sizeof(array) check as a sentinel value to find end of int array, therefore size of array in case A?

If I were to implement sizeof (intArray) , there is no liberty to access of sentinel value information ?

David Prun
  • 8,203
  • 16
  • 60
  • 86
  • It checks something you can't see/get hold of. – this Oct 19 '13 at 02:07
  • Shouldn't it check for a NULL value – sukhvir Oct 19 '13 at 02:08
  • 6
    `sizeof` does *not* "check `'\0'`" as the end of a `char` array. `char c[100] = "five"; printf("%zu\n", sizeof(c));` will print 100, not 4 or 5. You're thinking of `strlen()`. – Crowman Oct 19 '13 at 02:19
  • 2
    sizeof looks like a function, but it is executed at compile time; the compiler knows how big things are being allocated. – ChuckCottrill Oct 19 '13 at 02:22
  • sizeof(char[]) is not the same as strlen(char[]). sizeof(char[]) will not scan for '\0'! For any array type whose size is known at compile time, sizeof() will return its size (in elements, not necessarily in bytes!). In the case of your int[] array, sizeof(array) will return 6. –  Oct 19 '13 at 02:26
  • 1
    @elgonzo: `sizeof` will indeed yield a number of bytes. To get 6 in that example, you'd need `sizeof(array) / sizeof(array[0])` or similar. This isn't necessary for `char` arrays, since `sizeof(char)` is 1 by definition. – Crowman Oct 19 '13 at 02:40
  • @Paul: Yes. Aww..., what was i writing there. Sorry about that. –  Oct 19 '13 at 03:35

3 Answers3

14

sizeof does not check anything. It only looks like a function call, but it is really an operator, a compiler trick to insert the size as known to the compiler at compile time.

Here is how sizeof interacts with C arrays: when you declare an array, you specify its size as a constant, as a run-time integer expression, or implicitly by supplying a certain number of values to put into your array.

When the number of elements is known at compile time, the compiler replaces sizeof(array) with the actual number. When the number of elements does not become known until runtime, the compiler prepares a special implementation-specific storage location, and stores the size there. The running program will need this information for stack clean-up. The compiler also makes this hidden information known to the runtime portion of sizeof implementation to return a correct value.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I am not convinced! someone would have implemented for sure to find end of int[] array right? how can compiler return size arbitrarily? – David Prun Oct 19 '13 at 02:11
  • 1
    @DavidPrun It's not arbitrary, the length of the array and the size of `int` is right there in front of the compiler. – ta.speot.is Oct 19 '13 at 02:11
  • 5
    sizeof only works when the compiler knows the size. Try using it on an array parameter to a method -- you'll find it does not work. – Ernest Friedman-Hill Oct 19 '13 at 02:13
  • @DavidPrun The compiler sees you declaring/initializing your array, counts the entries, and remembers that number to tell the linker how much memory to allocate. When you use `sizeof`, the compiler simply plugs in that constant into the generated code as if you typed in a corresponding integer. – Sergey Kalinichenko Oct 19 '13 at 02:16
  • @dasblink and Ernest, you mean that I always have to rely on size of(array) in case of int[] array to print elements? is there no way to assign a int* pointer to arr[0] and print until end of array? – David Prun Oct 19 '13 at 02:16
  • 2
    Often people define functions to take both an array and an integer holding the size of the array as two separate parameters. – Ernest Friedman-Hill Oct 19 '13 at 02:18
  • @DavidPrun Correct, there's no way to do that. You need to pass the size to the caller along with the pointer - a very common pattern in working with arrays in C. – Sergey Kalinichenko Oct 19 '13 at 02:20
  • @Ernest and dasblink, while I appreciate your answer, I am trying hard to understand basics, if I were to implement sizeof (intArray) , there is no liberty to access of sentinel value information ? – David Prun Oct 19 '13 at 02:20
  • Correct. sizeof can not be implemented in C as a runtime function. The input it would need is not stored anywhere! The info exists at compile time though, and that's when sizeof operates. – Ernest Friedman-Hill Oct 19 '13 at 02:22
  • 2
    @DavidPrun There is no sentinel value, unless you put it there yourself (say, a negative 1). It is impossible to implement `sizeof` as a C function, because you lack the information necessary to tell the exact size. Moreover, the compiler loses that information as soon as you pass an array to a function: `sizeof` of an array parameter will return the same value, no matter how large the array that you pass really is. – Sergey Kalinichenko Oct 19 '13 at 02:23
  • 1
    @DavidPrun: You don't need to "rely" on anything. You'll already know how many elements there are in the array, because you just created it and gave it a definite size. – Crowman Oct 19 '13 at 02:31
  • There exists no runtime info for sizeof. See similar question here: http://stackoverflow.com/questions/492384/how-to-find-the-sizeofa-pointer-pointing-to-an-array – Tarik Oct 19 '13 at 02:48
  • @Tarik Not in C89. But in C99 with its variable-size arrays there is some - you wouldn't be able to do [this](http://ideone.com/fp0NPc) without a runtime support. In all other cases there's indeed no runtime involvement. – Sergey Kalinichenko Oct 19 '13 at 02:50
  • Wow, OK. I was not aware of this change. Would that work on a pointer to an array? – Tarik Oct 19 '13 at 02:58
  • @Tarik No, definitely not pointers to arrays: this was done specifically for variable-size arrays of C99 (although I wish they'd expanded it further). – Sergey Kalinichenko Oct 19 '13 at 03:06
  • 1
    @Tarik With a pointer the size is no longer part of the type. As it is, it's consistent with the compile-time equivalent. – tab Oct 19 '13 at 06:17
6

I think you're confusing string literals having a '\0' (null-terminator) in the end with arrays in general. Arrays have compile-time length known to the compiler 1. sizeof is an operator which gives the size based on the array length and the base type of the array.

So when someone does int a[] = {1, 2, 3}; there's no null-terminating character added in the end and number of elements is deduced as 3 by the compiler. On a platform where sizeof(int) = 4, you'll get sizeof(a) as 12.

The confusion is because for char b[] = "abc";, the element count would be 4 since all string literals have a '\0' automatically put up I.e. They are null-terminated automatically. It is not the sizeof operator which does a check for this; it simply gives 4 * sizeof(char) since for sizeof all that matters is the compile-time array length which is 4 = 1 + the number of characters explicitly stated in the string literal due to the nature of string literals in C.

However a character array not initialised by a string literal but with character literals doesn't have this quirk. Thus if char c[] = {'a', 'b', 'c'};, sizeof(c) would return 3 and NOT 4 as it is not a string literal and there's no null-terminating character. Again sizeof operator (not function) does this deduction at compile-time 2.

Finally, how the sizeof operator itself is implemented to do this, is an implementation detail not mandated by the standard. A standard talks about conditions and results. How they're achieved by implementations isn't a concern of the standard (or to anyone except the developers who implement it).


1 C99 introduced Variable Length Arrays (VLA) which allows arrays to have dynamic size.

2 Only for VLAs the sizeof operator and its operand are evaluated at run-time

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Well, this example shows that sizeof operates at runtime: http://ideone.com/fp0NPc – Tarik Oct 19 '13 at 03:09
  • @Tarik: Dynamic sized arrays are a feature of C99 and not available in C++ (including C++11). Unless the OP specifically asks there's no reason to bring this up and confuse a beginner. – legends2k Oct 19 '13 at 03:53
  • Even in C99 [sizeof is evaluated at compile time except for VLAs](http://stackoverflow.com/a/10078362/183120) which is not the OPs question centred on. – legends2k Oct 19 '13 at 05:27
  • You insisted that sizeof was a compile time operator without even the slightest hint to the VLA "exception" : "Again sizeof operator (not function) does this deduction at compile-time". Alternatively, to "avoid confusing a beginner", we could just refrain from mentioning wether sizeof operates at compile time or otherwise. – Tarik Oct 19 '13 at 06:16
  • I still hold my words, please lookup the standard (even in C99), sizeof is an operator and not a function. Also when the OP hasn't tagged it as C99, I prefer referring to the famous C89 standard. When teaching, it's common that a general rule is taught first and then the exceptions, instead of avoiding the concept altogether. – legends2k Oct 19 '13 at 06:21
  • @Tarik: Nevertheless, I updated the answer with footnotes to address your concern. Hope it's fine now :) – legends2k Oct 19 '13 at 16:14
  • Thanks for your follow up and sorry if I sounded too picky. +1 – Tarik Oct 19 '13 at 18:30
  • Not at all; there's nothing wrong in your striving for correctness, after all every programmer should try to learn more from fellow ones and not let ego come in the way. Without your comment I wouldn't have looked deeper into _sizeof_ & VLAs. Thanks! – legends2k Oct 20 '13 at 05:22
2

sizeof is not a function, but a compile-time operator, that is replaced with the size of the variable. In case of true arrays (not pointers) it is replaced with the size in bytes of the content of the array, because it's knows at compile time;

Try the following to convince yourself:

void print_size(int[] array)
{
  printf("%u\n", sizeof(array)); //Prints 4 (= sizeof(int*))
                                 //May print 8 on 64b architectures
}

int main()
{
  int array[] = {2,33,4,56,7,8};
  printf("%u\n", sizeof(array)); //Prints 24 (= 6*sizeof(int))
  print_size(array);
  return 0;
}

This is because, inside of main, the compiler knows that array is an array of 6 ints, while the function print_size may be called with any array, and so its size is not known in advance: it is treated just like a int* (except that I'm not sure if it's a lvalue)

Giulio Franco
  • 3,170
  • 15
  • 18
  • The idea is right, but `sizeof` is an *operator*, not a "compiler instruction". – Crowman Oct 19 '13 at 02:20
  • Is it ok now? I left compile-time there, because I want it to be clearly stated. – Giulio Franco Oct 19 '13 at 02:23
  • Well, this example shows that sizeof operates at runtime: http://ideone.com/fp0NPc – Tarik Oct 19 '13 at 03:12
  • @Tarik That's a nice point. This construct was only introduced with the C99 standard, and wasn't supported before. I tried it on my compiler (GCC). I'm not really into assembly, but it looks like the compiler allocates a stack segment in order to hold the array, and writes the size of the array inside a field of the stack frame. So, yes, variable-size arrays are handled at runtime. – Giulio Franco Oct 19 '13 at 10:46