0

Extremely simple code with output I don't understand...

#include  <iostream>

using namespace std;

int main() {

    char text1[] = {'v', 'e', 'r', 'y'};
    cout << text1 <<  endl;
    char text2[] = "strange";
    cout << text2 << endl;

    return 0;
}

For some reason I get this output:

very�>��

strange

Every time the output is 'very' followed by the same amount of characters in the second array. This outputs correctly if I change the first line to

char text1[] = "very";

or if I don't declare and cout a second array.

Must have something to do with the way char is initialized with {'', '', '', ...}.. I notice that in this case the sizeof(text1) is 4 and in the case of using char text1[] = "very"; the sizeof(text1) is 5 with the last position being left blank. When declaring the second char the first char sizeof is still accurate however the second char is positions immediately after the first char in memory.

If I rewrite the program like this...

int main() {

    char text1[] = {'v', 'e', 'r', 'y'};
    char text2[] = "strange";
    cout << text1 <<  endl;
    cout << text2 << endl;

    return 0;
}

The output becomes:

verystrange

strange

It seems that if I declare more char arrays it always slips the last one right in after the first one (text1[]) and it bumps the others forward in memory to make room. It only happens with using {}; to initialize. Really just wondering what's going on here... I can't see this causing any problems in a well written program.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Have you happen to come across, somewhere in your C or C++ book, that plain character text strings must end with a null byte, or `'\0'`? Because that's the only way C and C++ works with plain literal strings? – Sam Varshavchik Mar 04 '20 at 03:22
  • 1
    `cout << ` expects a null-terminated string, and your first `char[]` array isn't null-terminated. Your second one is. – user207421 Mar 04 '20 at 03:22
  • 1
    Does this answer your question? [C String Null Zero?](https://stackoverflow.com/questions/4424487/c-string-null-zero) – Brian61354270 Mar 04 '20 at 03:22
  • To be clear if I only declare one char array the output is normal. Its only if the program declares a second array, anywhere in main() that the program scrambles extra characters on the first array. – CrazyDiamond Mar 04 '20 at 03:24
  • thanks that does explain it... but why does this only occur when a second array is declared I wonder? – CrazyDiamond Mar 04 '20 at 03:25
  • 1
    @CrazyDiamond The only reason you don't print garbage when using only one array is that the memory following the first array just so happens to be `0`s (perhaps since you're compiling with debug flags?). When you use two arrays, the second array follows the first in stack memory, and so the runtime can't tell where the first ends and the second begins. – Brian61354270 Mar 04 '20 at 03:27
  • Makes sense... is there a way to flag this answered? – CrazyDiamond Mar 04 '20 at 03:28
  • @CrazyDiamond *but why does this only occur when a second array is declared I wonder?* -- The bottom line is that you don't know where the terminating null will be if you don't null-terminate the array yourself. Where the array is in memory is up to the compiler and compiler options. – PaulMcKenzie Mar 04 '20 at 03:33
  • If I understand you correctly cout expects a null character at the end.. if I happened to put a space ... ' ' ... into the char array it would cout just up to that space. Also c++ knows full well what the sizeof the char array is and it is just the way cout is built that is causing the crazy output? – CrazyDiamond Mar 04 '20 at 03:34
  • Thank you guys... nice to have a forum like this available. I feel very informed about what is happening here. That was fast and you guys are great. I'm not sure how to mark as answered or if we could just delete this post. Thanks a ton. – CrazyDiamond Mar 04 '20 at 03:37
  • @CrazyDiamond in C/C++, [arrays and pointers](https://stackoverflow.com/questions/10186765/what-is-the-difference-between-char-array-and-char-pointer-in-c) are two distinct types. In general, you can't pass an array to a function, but you can pass a pointer to the first element of an array. This is precisely how `cout::operator<<(const char*)` is implemented. It does not know the length of the array behind the pointer, so it keeps read until it finds the trailing sentinel. – Brian61354270 Mar 04 '20 at 03:37
  • @CrazyDiamond I've attempted to compile (no pun intended) the discussion above into an answer below. – Brian61354270 Mar 04 '20 at 03:49

1 Answers1

0

To summarize the responses in the comments, in C, "strings" don't have an associated length. Rather, the end of a "string" it denoted by a trailing null character, i.e. 0.

When you initialize an character array using

char text1[] = {'v', 'e', 'r', 'y'};

you create an array of precisely four characters with no trailing null. If you attempt to pass this "string" to a function which expects a trailing-null-delimited string, such as std::cout::operator<<(const char*), you will produce undefined behavior since arbitrary memory after the string will be read until a null character is found.

In your example from the comments, the only reason you don't print garbage when using only one array is that the memory following the array just so happens to be 0s (perhaps since you're compiling with debug flags?). However, when you use two arrays, the second array follows the first in stack memory, and so cout::operator<< can't tell where the first ends and the second begins.

Brian61354270
  • 8,690
  • 4
  • 21
  • 43