-2

Here my C Code

#include <stdio.h>

int main()
{
    char c[3] = "abc";
    char a[6] = "Shamal";

    printf("%s\n\n", c);
    printf("%s\n\n", a);

    return 0;
}

Here the output is

abcW?

Shamal

The string with 6 characters shows the string properly while the string with 3 characters shows W? at the end of the code.

I know we need to put the null character '\0' to terminate the string. But here the both strings doesn't have the null character yet only one works properly. What is the reason for this?

S. Sandeep
  • 237
  • 3
  • 11
  • 7
    The reason is _undefined behavior_ is _undefined_. Or to put it another way, there is no reason, it just is the way it is. – tkausl Sep 17 '17 at 06:19
  • 1
    Compile with all warnings and debug info (`gcc -Wall -Wextra -g`) – Basile Starynkevitch Sep 17 '17 at 06:29
  • 2
    `c` and `a` are NOT *strings* (there is no *nul-terminating* character), they are *character arrays*. If you declare as, e.g. `char c[] = "abc";` (or `char c[4] = "abc";`), then the compiler will include a *nul-terminating* character at the end based on your *string initialization*. You are not providing enough space (short by 1-char) to create strings. (P.S. the *nul-terninating* character is simply decimal `0`, or character `'\0'` -- they are equivalent) – David C. Rankin Sep 17 '17 at 06:35
  • just to add some unsolicited pedantry, according to standards it should be `int main(void)`. – ShinTakezou Sep 17 '17 at 09:13

3 Answers3

2

As the comment above says, undefined is undefined, but exact answer to your question is that it accidentally happens that the memory byte right after the first string is not 0, but 'W' and then '?' and after that is 0 which terminates a string.

With the second string, it happened that a byte right after the string is accidentally 0 so it is printed correctly.

Try reordering initialisation and see if the output changes (most likely it will).

isp-zax
  • 3,833
  • 13
  • 21
2

Whenever you write something like char c[4] = "abc"; or char c[] = "abc";, the string abc is stored memory (and you can't change this string) with a \0 being appended automatically. In both of your cases you are not allocating space for the terminating NUL character.

For char a[6] = "Shamal";, if you would loop over the characters and print them by index 0 through 5, you will get back your string.

Now, if you notice carefully, you have set aside space for six characters only and there is no space for the \0. The \0 might be written to space that you do not own, i.e. just after l. At this stage you have overran your buffer space that you thought would be enough. This itself is enough to cause UB. Another problem arises when you ask printf to print out your string. printf keeps on printing until a \0 is found. Once you invoke UB, there's no telling what will happen.

Check this for another explanation.

babon
  • 3,615
  • 2
  • 20
  • 20
1

Continuing from my comment, you are simply not providing adequate space to create character strings in your initializations. The following creates character arrays without space for the nul-terminating character:

char c[3] = "abc";
char a[6] = "Shamal";

You will not receive any warnings during compilation because the initializations are valid initialization for character arrays -- not strings.

For example, char c[3] = "abc";, results in the following sequential bytes in memory:

    | a | b | c |

that is a valid character array of 3-elements and each element can be indexed as c[0], c[1], c[2]. However, to use c as a string, c requires the following 4 sequential bytes in memory:

    | a | b | c |\0|

To correct the issue and allow the compiler to include the nul-terminating character as part of your initialization, either do NOT provide a size for the array and the compiler will automatically size the array to provide the additional space needed to include the nul-character, e.g.

char c[] = "abc";
char a[] = "Shamal";

Or (more prone to error), provide room for the nul-character yourself, e.g.

char c[4] = "abc";
char a[7] = "Shamal";

Both will result in c and a containing the nul-terminating character, allowing each to be used as strings in your code.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85