简体   繁体   中英

What's the trailing symbols within an char array which initialized with brace-enclosed lists in clang?

#include <stdio.h>

int main(int argc, const char *argv[]) {
  char name1[] = {'f','o','o'};
  char name2[] = "foo";
  printf("%s\n", name1);
  printf("%s\n", name2);
  return 0;
}

running the code above results in:

foox\363\277\357\376
foo
Program ended with exit code: 0

So, what's the difference between these 2 initializers?

name1 is an array of three characters {'f', 'o', 'o'} .

name2 is an array of four characters {'f', 'o', 'o', '\0'} .

printf("%s", ...) expects an array terminated with a null character. Because name1 isn't, you start dereferencing characters past the end of the array which can have the traditional undefined behavior.

The first array ( ie, {'f','o','o'} ) will not have the null character '\0' , wheres the second ( ie, "foo" ) will.

The printf specification when using the %s says the following:

If no l modifier is present: The const char * argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating null byte ('\0'); if a precision is specified, no more than the number specified are written. If a precision is given, no null byte need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating null byte.

Since, your printf did not include the precision, it will write up characters from the array until reaching the null byte ( '\0' ). Consequently, in the case of the char name1[] = {'f','o','o'}; resulting in the printf write up characters out of the memory that was allocated for the name1 array. Such behaviour is considered to be undefined .

This is the reason why printf("%s\n", name1); prints foo plus some extra symbols from the next positions in memory that should not have been accessed , whereas with printf("%s\n", name2); it prints exactly the string " foo" as it is.

There are no trailing symbols in the array.

But printf 's %s format expects a string , and the array name1 isn't a string: by definition, C strings are zero terminated … and your array isn't. So the behaviour is undefined, and what seems to happen in your particular case is that printf continues printing random values that happen to be in memory just behind the contents of name1 .

In C language if you are initializing string with character by character initializer you need to put '\0' which is NULL/terminating character to indicate the end of string. so name1 should be {'f', 'o', 'o', '\0'}

x\363\277\357\376 that you can see at the end of your output is just garbage value which is printed just because printf could not find '\0' at the end of your string name1.

For name2 you used double quote to initialize the string which automatically puts a '\0' at the end of string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM