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?

3
  • 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 Commented Dec 7, 2018 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. Commented Dec 7, 2018 at 17:17
  • Don't ignore compiler warnings, the code invokes undefined behaviour for more than one reason. Commented Dec 7, 2018 at 17:47

2 Answers 2

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?

Sign up to request clarification or add additional context in comments.

3 Comments

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?
No, it has undefined behavior, according to the constraint quoted in the other answer.
Just came to know from discussion on this answer 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?
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.

1 Comment

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?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.