0

Code:

char x[]={'i',' ' ,'l','i','k','e',' ','c','!'};
printf("%s",x);

Result:

i like c!�@i like c!�@

I tried to print char array that not terminated with '\0' and using the string specifier %s in printf.

I expected for error but which didn't happen. Instead the array was printed with some other characters. Why is that?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Adam z
  • 1
  • 6
    C is a compiled language. The training wheels are off. If you forget to null-terminate a string, and then try to print it, `printf` will keep going past the end of the string until it encounters a null character outside of the string (or encounters an access violation). – Tom Karzes Aug 03 '23 at 06:58
  • 2
    Telling `printf()` that an argument is a 0 terminated string and then giving it something else is undefined behavior. Don't do that. Use `fwrite()` or put a length in the format directive. – Shawn Aug 03 '23 at 06:59
  • 1
    What "error" did you expect to happen? – Jabberwocky Aug 03 '23 at 06:59
  • 1
    Please read [this](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). It is the single most important piece of information about C. – n. m. could be an AI Aug 03 '23 at 07:04
  • 1
    There are tools that try to help catching these type of errors: https://godbolt.org/z/7ETr54TEE – Bob__ Aug 03 '23 at 08:11
  • `%9s` is the correct format to print a nine-character array. – stark Aug 03 '23 at 11:44

3 Answers3

4

Passing something other than a (NUL-terminated) string to %s is undefined behaviour. Anything can happen.

ikegami
  • 367,544
  • 15
  • 269
  • 518
2

From the C Standard (7.21.6.1 The fprintf function, the same is valid for printf)

s If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.273) Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.

and

9 If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

So the conversion specification %s expects that the used character array as the corresponding argument contains the terminating null character '\0'. Otherwise the behavior is undefined because the function tries to access the content of memory outside the character array until the terminating null character is encountered.

Answering your question

I expected for error but which didn't happen. Instead the array was printed with some other characters. Why is that?

I can say that undefined behavior means that anything can occur. In this particular case the function outputted some redundant symbols below the character array until the terminating null character was encountered. In other cases a program can be abruptly terminated.

Instead you could write

printf("%.*s", ( int )sizeof( x ), x );

and according to the first quote from the C Standard "if the precision is specified, no more than that many bytes are written".

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

I tried to print char array that not terminated with '\0' and using the string specifier %s in printf.

This is not possible or at least not easy since the argument for %s should be a valid, \0 terminated, C string.

If you know that no char element of the array is the NUL character (coded 0), you might read the documentation of printf(3) then use %*s

Your array of chars should in practice be conforming to the locale setting. On my Linux computer, it should be correctly UTF8 encoded. See also locale(7).

Read also some C standard document, at least n1570 or better

With good compilers like recent GCC, enable all warnings and debug info, so compile with

 gcc -Wall -Wextra -g

then improve your code to get no warnings.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547