2
#include <stdio.h>

char s[3] = "Robert";
int main()
{
    printf("%s",s);
}

Output: Rob

How does this get printed properly? The string is not null terminated. I saw the assembly. It used .ascii for storing "Rob" which is not null terminated. I expected some garbage along with Rob to be printed. Can someone explain me this behaviour?

jww
  • 97,681
  • 90
  • 411
  • 885
Anup Buchke
  • 5,210
  • 5
  • 22
  • 38
  • 11
    It is simply *undefined behaviour*. – juanchopanza Apr 26 '14 at 22:18
  • 1
    Probably because you got lucky and the next byte in memory after `s` is `\x00`. – Paulo Bu Apr 26 '14 at 22:18
  • 1
    I am just trying to learn how character arrays and literals are stored. – Anup Buchke Apr 26 '14 at 22:19
  • [Which compiler is this?](http://coliru.stacked-crooked.com/a/b210d7da3b4e6855) – chris Apr 26 '14 at 22:19
  • @anup.stackoverflow, Try it [without `-fpermissive`](http://coliru.stacked-crooked.com/a/7c593f9816026719). I recommend never using that option unless you absolutely must. – chris Apr 26 '14 at 22:20
  • I have not used -fpermissive. And it did gave me warning. I am just trying to play around. I initially thought that compiler knows the array size and truncates the array and appends null character. But as juanchopanze said. It might be undefined behaviour. – Anup Buchke Apr 26 '14 at 22:23
  • 4
    FWIW, this was allowed in C. C++11 § C.1.7 [diff.decl] says *In C++, when initializing an array of character with a string, the number of characters in the string (including the terminating ’\0’) must not exceed the number of elements in the array. In C, an array can be initialized with a string even if the array is not large enough to contain the string-terminating ’\0’* – chris Apr 26 '14 at 22:25
  • 1
    Thanks Chris for pointing to the rules.. I tried out in c++. It does give error. g++ enforces it. The more I learn about about c and c++ , i realize that they are different in many aspects. – Anup Buchke Apr 26 '14 at 22:29
  • Hmm, I didn't even notice the C tag before now, so that never even came to mind. It would make sense for GCC to compile it in C without an error then. – chris Apr 26 '14 at 22:31
  • Maybe if you add a second variable `char dummy[] = "garbage"` after the definition of `s` you'll get your garbage appended. Or maybe not. It's hard to predict (and I'm too lazy to try). Also changing the `3` to `4` may make a difference (in case global variables are aligned at four-byte boundaries). – celtschk Apr 27 '14 at 05:48

1 Answers1

4

Your "Rob" has been stored in an extra section of the executable. The sections in an executable are aligned, i.e. the section with the data is padded with 0 until the next section. So printf got "its" 0 from the section padding. To illustrate:

#include <stdio.h>

char dummy[] = "ocop";
char s[3] = "Robert";
char second[] = "in Hood";
int main( void )
{
    printf("%s",s);
    return 0;
}

Output (MinGW-GCC w/o optimization): Robin Hood
Output (MinGW-GCC with optimization): Robocop

Now there is no 0 from the padding but the begin of the next string which will be outputted as well.

rkhb
  • 14,159
  • 7
  • 32
  • 60