0

I was trying out some array related stuff in C.

I did following:

char a2[4] = {'g','e','e','k','s'};
printf("a2:%s,%u\n",a2,sizeof(a2));
printf("a2[4]:%d,%c\n",a2[4],a2[4]);

In this code, it prints:

a2:geek,4
a2[4]:0,

In this code, it prints:

a2:geek�,4
a2[4]:-1,� 

Both code run on same online compiler. Then why different output. Is it because the standard defines this case as undefined behavior. If yes, can you point me to exact section of the standard?

MsA
  • 2,599
  • 3
  • 22
  • 47
  • C string is composed of a sequence of characters ending with a `\0`. When you do the `a2[4]`, not only the array doesnt have enough space for all the characters.. it also doesnt have the `\0` at the end. [Reference for C-String definition](https://stackoverflow.com/questions/12203339/c-string-definition-in-c-c) – wendelbsilva Dec 07 '18 at 17:16
  • the printf format specifier %s expects a null terminated string. you are seeing undefined behavior when passing a non null terminated string to printf. – Bwebb Dec 07 '18 at 17:17
  • Don't ignore compiler warnings, the code invokes undefined behaviour for more than one reason. – too honest for this site Dec 07 '18 at 17:47

2 Answers2

2

Yes, this is undefined behavior. I don't have a reference to the standard, but %s format is for printing null-terminated strings, and you don't have a null terminator on a2. And when you access a2[4] you're accessing outside the array bounds, another cause of undefined behavior.

Finally, the array initializer also causes undefined behavior, see Is it ok to have excess elements in array initializer?

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Also assigning longer string to shorter array `char a[5] = "geeks";` itself has no undefined behavior associated with it, right? Its just that excess characters in the string will be ignored, right? – MsA Dec 08 '18 at 08:40
  • No, it has undefined behavior, according to the constraint quoted in the other answer. – Barmar Dec 08 '18 at 20:15
  • Just came to know from discussion on [this answer](https://stackoverflow.com/a/53682584/6357916) that `char a[5] = "geeks";` is valid (not UB) but `char a[5] = "geeks2";` is invalid / UB. In other words, having no space for `\0` is ok, but its not ok to have no space for non-`\0` character. This is correct, right? – MsA Dec 09 '18 at 02:32
0

The presence of excess initializers violates a constraint in C 2018 6.7.9 2:

No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

'k' and 's' would provide initial values for a2[4] and a2[5]. Since a2[4] or a2[5] do not exist, they are not contained within a2, and the constraint is violated.

That said, compilers will typically provide a warning then ignore the excess initializers and continue. This is the least of the problems in the code you show and has no effect on the output you see.

After the definition of a2, you print it using %s. %s requires a pointer to the first character in a sequence of characters terminated by a null. However, there is no null character in a2. The resulting behavior is not defined by the C standard. Often, what happens is a program will continue to print characters from memory beyond the array. This is of course not guaranteed and is especially unreliable in the modern high-optimization environment.

Assuming the printf does continue to print characters beyond the array, it appears that, on one system, there happens to be a null character beyond the array, so the printf stops after four characters. When you later print a2[4] (also behavior not defined by the C standard) as an integer (%d) and a character (%c), we see there is indeed a null character there.

On the other system, there is a −1 value in the memory at a2[4], which displays as “�”. After it, there are presumably some number (possibly zero) of non-printing characters and a null character.

Additionally, you print sizeof(a2) using the printf specifier %u. This is incorrect and may have undefined behavior. A proper specifier for the result of sizeof is %zu.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Also assigning longer string to shorter array `char a[5] = "geeks";` itself has no undefined behavior associated with it, right? Its just that excess characters in the string will be ignored, right? – MsA Dec 08 '18 at 08:39