1

I asked this question as one of multiple questions here. But people asked me to ask them separately. So why this question.

Consider below code lines:

char a[5] = "geeks"; //1
char a3[] = {'g','e','e','k','s'}; //d
printf("a:%s,%u\n",a,sizeof(a)); //5
printf("a3:%s,%u\n",a3,sizeof(a3)); //j
printf("a[5]:%d,%c\n",a[5],a[5]);
printf("a3[5]:%d,%c\n",a3[5],a3[5]);

Output:

a:geeksV,5
a3:geeks,5
a[5]:86,V
a3[5]:127,

However the output in original question was:

a:geeks,5
a3:geeksV,5

The question 1 in original question was:

  1. Does line #1 adds \0? Notice that sizeof prints 5 in line #5 indicating \0 is not there. But then, how #5 does not print something like geeksU as in case of line #j? I feel \0 does indeed gets added in line #1, but is not considered in sizeof, while is considered by printf. Am I right with this?
  1. Realizing that the output has changed (for same online compiler) when I took out only those code lines which are related to first question in original question, now I doubt whats going on here? I believe these are undefined behavior by C standard. Can someone shed more light? Possibly for another compiler?

Sorry again for asking 2nd question.

3
  • 1
    for a[5] you are storing geeks with a NULL character which takes up 6 spaces. So you have undefined behaviour. Commented Dec 7, 2018 at 5:24
  • 1
    char a[] = "geeks"; would have given you the behavior you were looking for. Commented Dec 7, 2018 at 5:29
  • If you don't see the difference, "geeks" is a string-literal initializer. The '\0' is always added at the end. Commented Dec 7, 2018 at 5:30

2 Answers 2

2
char a[5] = "geeks"; //1

Here, you specify the array's size as '5', and initialize it with 5 characters. Therefore, you do not have a "C string", which by definition is ended by a NUL. (0).

printf("a:%s,%u\n",a,sizeof(a)); //5

The array itself still has a size of 5, which is correctly reported by the sizeof operator, but your call to printf is undefined behaviour and could print anything after the arrray's contents - it will just keep looking at the next address until it finds a 0 somewhere. That could be immediately, or it could print a 1000000 garbage characters, or it could cause some sort of segfault or other crash.

char a3[] = {'g','e','e','k','s'}; //d

Because you don't specify the array's size, the compiler will, through the initialization syntax, determine the size of the array. However, the way you chose to initialize a3, it will still only provide 5 bytes of length. The reason for that is that your initialization just is an initialization list, and not a "string". Therefore, your subsequent call to printf also is undefined behaviour, and it is just luck that at the position a3[5] there seems to be a 0 in your case.

Effectively, both examples have the very same error.

You could have it different thus:

char a3[] = "geeks";

Using a string literal for initialization of the array with unspecified size will cause the compiler to allocate enough memory to hold the string and the additional NUL-terminator, and sizeof (a3) will now yield 6.

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

2 Comments

So 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?
Yes. The difference is that your specification of the array's size limits the number of characters copied to the string, the initialization itself will not cause a buffer overrun. However, you cannot treat the array as a string as the terminating null is or might be missing. If you omit the size specification, the compiler will make room for all characters in your initialization string, PLUS the 1 byte for the nul-terminator.
1

"geeks" here is a string literal in C.

When you define "geeks" the compiler automatically adds the NULL character to the end. This makes it 6 characters long.

But you are assigning it to char a[5]. This will cause undefined behaviour.

As mentioned by @DavidBowling, in this case the following condition applies

(Section 6.7.8.14) C99 standard.

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array

the elements "geeks" will be copied into the array 'a' but the NULL character will not be copied.

So in this case when you try to print the array, it will continue printing until it encounters a \0 in the memory.

From the further print statements it is seen that a[5] has the value V. Presumably the next byte on your system is \0 and the array print stops.

So, in your system, at that instance, "geeksV" is printed.

8 Comments

This is not accurate. For example, the MSVC compiler does not add a zero to the end of "geeks".
@D.Go -- "geeks" is a string literal that causes an array of 6 chars to be initialized in static memory at compile time, and a null terminator is added at this time. That seems like what this answer is talking about. But....
@D.Go - Please refer to Section 6.4.5 of C99 standard "In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals"
char a[5] = "geeks"; does not cause undefined behavior. There is no null terminator in a[] after initialization though, so a[] is not a string in this case. Treating a[] as a string may lead to undefined behavior.
|

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.