Search code examples
cstringpointersputs

What may the C program output if we assign a character without ending with a null character in different declaring ways?


I have been reading C Primer Plus (5th edition) by Stephen Prata. The Program listing 11.9 is a program to show what may the puts() function do if we declare a string and assign a value without an ending null character. (Of course this is viewed as a grammar mistake, but I want to know what error will this bug cause.) I experimented on my computer (with CodeBlocks my ide) a similar program, and tried different ways to declare the string.

For the program

#include <stdio.h>

int main()
{
     char a[]={'a','b','c','d'};
     char b[100]="Stack Overflow";
     puts(a);
     return 0;
}

in which I used a[] to declare the string, the program indeed output some thing other than abcd . I tried several times, and it always output abcd< and an empty line:

output:

abcd<

If I declare the string by a[100] , i.e. the program

#include <stdio.h>

int main()
{
     char a[100]={'a','b','c','d'};
     char b[100]="Stack Overflow";
     puts(a);
     return 0;
}

Then it seems quite normal. The program always output abcd and an empty line after I have repeated several times:

output:

abcd

If I use the pointer to declare the string:

#include <stdio.h>

int main()
{
     char *a={'a','b','c','d'};
     char b[100]="Stack Overflow";
     puts(a);
     return 0;
}

Then it only output an empty line:

output:

Why different ways of declaring the string, which is assigned a value without an ending '\0' yields different outputs?


Solution

  • char a[100]={'a','b','c','d',};

    If an aggregate (an array or structure) is explicitly initialized but not completely, the elements or members without initializers are implicitly initialized the same way as objects with static storage duration (per C 2018 6.7.9 21). For char elements, that means they are initialized to zero (per 6.7.9 10). So, after a[0] through a[3] are initialized with the given character codes, a[4] is initialized to zero. So the string beginning at the start of a is null terminated, by the null character in a[4], and passing that string to puts prints a string in the ordinary way.

    char *a={'a','b','c','d',};

    This is not a proper way to initialize a. {'a','b','c','d',} does not represent an array; it is a list of initial values. Since a is declared as a pointer, it should be initialized with a single value that is a pointer.

    When you compiled this, the compiler warned you that 'a' was the wrong type to initialize a, and it warned you there were excess initializers in the list.

    When the compiler proceeded after this warning, it converted 'a' to a pointer, which typically yields an invalid address. It is surprising that puts(a) did not cause the program to crash in attempting to access that address. (Perhaps you are running in a GUI, saw an empty output window, and did not notice a separate message about the program crashing?) If the program did not crash, there could have been a zero byte at the address a was initialized with, so passing a to puts printed nothing.