array of char without '\0' terminated

Hello,

from previously asking on here I've understood that the << operator has been overloaded for C-strings (char arrays that are 0 terminated), to print it as a std::string. But what happens if you do not allocate the 0?

1
2
3
4
5
6
char arr3[4] = { 'b', 'a', 'd' };
cout << arr3; //prints bad, as expected.

char arr3[3] = { 'b', 'a', 'd' };
    
    cout << arr3; //weird output 
Well if there is no room for a \0, then you don't have a \0, and therefore you see "bad" plus whatever is in memory until
- a \0 is found
- you run out of memory and the OS kills the program with a segfault.
this program runs fine even without null termination
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <cstring>
using namespace std; 

int main(){
	char ar[10] = {'a','b','c'}; // ar[3] runs fine also
	cout << sizeof(ar) << endl;
	for(auto x:ar) cout<< x;
	cout << endl;
	cout<< strlen(ar) << endl;
return 0; 
} 
> this program runs fine even without null termination
> char ar[10] = {'a','b','c'};
Except it does have \0
Seven of them to be precise.

As soon as you have at least ONE initialiser in an array, all the remainder elements you don't specify are filled with 0,0.0,'\0',nullptr (depending on the type).
what about this one
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <cstring>
using namespace std; 

int main(){
	char ar[3] = {'a','b','c'};
	cout << sizeof(ar) << endl;
	for(auto x:ar) cout<< x;
	cout << endl;
	cout<< strlen(ar) << endl;
return 0; 
} 
> what about this one
That will blow up as soon as you try to do strlen().
Unfortunately, it probably won't. Quite often these errors are silent and appear to be working fine until they don't and then debugging it becomes a huge ordeal.

one thing that can happen, is say you had this:
int y = 42;
char oops[3];
int x = 10;
sprintf(oops, "oh noes"); //it has a terminal zero, but its out of bounds.
cout << x << oops << y; //good chance x is damaged, as the sprintf overflow would run the bytes into the integer, silently changing its value. Or it could crash. Crashing here is great, you can go fix it. Silently changing x's value will drive you nuts trying to find the problem in a big program. It may also change y's value, on some systems, depending on which way the stack goes on your compiler. And changing x's value can damage the string too. Its a mess when it 'works fine'. To test these things compile in release not debug settings or the padding between variables for debugging hides this issue.

Last edited on
i wonder how strlen() is working there without null termination
That's the thing about undefined behavior; it's undefined. Your program could crash for going out of bounds, or work just fine. Or order you a pizza. Avoid it!
ya, surely i will use '\0' if i use c strings, although i prefer std string. i made the program to show that what op wrote "weird output " is actually working, it worked on gcc, clang and visual studio compiler.(i'm not telling to program that way). so how op get that weird output?
maybe for declaring arr3 twice.
Well that's the whole thing about undefined behaviour.

Sometimes you can make the most horrendous screw-ups and the thing will still do exactly what you expect, and you declare success.

Other times, the tiniest infraction of the rules gets you your ass handed to you on a plate.

Testing on multiple compilers helps to flush out false assumptions, but as you've seen, it's no a fool-proof way of finding problems.

A particular issue with this test might be that it's only 3 characters long, which is just short enough to fit inside a machine word - and you're going to get a free \0 in the right place completely by accident. With a longer string, different compilers might do different things.

Ultimately, the only way to proceed is to know what the language is supposed to do, as specified by the ISO committee in the various language standards.

Trying to reverse engineer the language spec from observing the corner cases of what a compiler does (or doesn't) is not the way to go.


@salem c, you are getting me wrong. we must definitely try to program the standard way.
the intention of my above code is to show that i didn't see the "weird output" as kyrresc, that's all. you must keep 1 space for '\0' no doubt about that.
Topic archived. No new replies allowed.