Q:

Printing gibberish after printing all characters c++

I have the following code: 
# include <iostream>

using std::cout;

const int ARRAY_SIZE = 15;

union one4all
{
    int int_value;
    long long_value;
    double double_value;
    char char_value[ARRAY_SIZE];
};

int main()
{
    one4all x;
    for (int i = 0; i < ARRAY_SIZE; ++i)
    {
        x.char_value[i] = (int)(i + 97);
    }

    cout << x.char_value << '\n';

    system("pause");
}

This code was printing gibberish after the last character value. Then, after some research it says that the reason is because it cannot detect a terminating character and hence, it keeps on printing. 
https://i.stack.imgur.com/7MFvS.png

So, I updated my code to this:
# include <iostream>

using std::cout;

const int ARRAY_SIZE = 15;

union one4all
{
    int int_value;
    long long_value;
    double double_value;
    char char_value[ARRAY_SIZE];
};

int main()
{
    one4all x;
    for (int i = 0; i < ARRAY_SIZE; ++i)
    {
        x.char_value[i] = (int)(i + 97);
    }

    x.char_value[ARRAY_SIZE - 1] = '\0';

    cout << x.char_value << '\n';

    system("pause");
}

This worked perfectly because it has a terminating character at the end. 
https://i.stack.imgur.com/WVsBB.png 
This raised questions: 
Why did it keep printing after the 15th character? I know that it could not detect any terminating character, but hey! it knew the size of the character array? 
If for some reason it cannot detect the size of the array, why did it not bombard my screen with more gibberish characters and what motivated it to stop printing the gibberish characters? 

A:

Why did it keep printing after the 15th character? I know that it could not detect any terminating character, but hey! it knew the size of the character array?

"it" might if you mean the compiler generally, but you called a streaming function operator<<(std::ostream&, const char*) - which is only matched because the array has decayed to a pointer and the length is lost.  That's just the way the Standard Library function has been written.
If it tried to be smarter, it's not clear what would work best anyway: say the Standard Library provided...
template <size_t N>
std::ostream& operator<<(std::ostream&, const char(&)[N]);

...so knowledge of the array size would be available - should it always stream a number of characters determined by the character array size, or stop early if it hits a NUL?
It'd still be a pain that if you called a non-template function with a char[] argument, that will tend to decay to a char* function argument, and the called function couldn't then provide the array size if it tries to stream the value.
Summarily, the idea of a streaming operator utilising knowledge of the array size just doesn't hold up as text buffers and pointers to them are passed around a program.

