Enquiry about cout for char

Third cout statement prints two Hello instead of one!!!


#include <iostream>
#include <string>
using namespace std;
//Ctrl+Shift+C to comment
//Ctrl+Shift+X to uncomment

int main()
{
char foo[] = "Hello";
char bar[] = "World!";
char foo1[6] = "Hello";
char myword[5] = {'H','e','l','l','o'};
//char once initialized cannot be assigned values (again)
cout<<foo<<endl;
cout<<bar[0]<<endl;
cout<<myword<<endl;
cout<<myword[0]<<endl;

cout<<sizeof(foo)<<endl;
cout<<sizeof(foo1)<<endl;

string monkey ("My name is");
string house ("Mohammad");
string monkeys = monkey +" " + house; //Try concatenation
cout<<monkeys<<endl;

return 0;
}
Well, I get that output, actually.

1
2
3
4
5
6
7
8
9
10
11
xxx@yyy:~/Android$ c++ test.cpp
xxx@yyy:~/Android$ ./a.out
Hello
W
Hello
H
6
6
My name is Mohammad
xxx@yyy:~/Android$ 
The cout << operator assumes the string is null terminated (i.e. ends with '\0').

This should work better:
 
char myword[6] = {'H','e','l','l','o','\0'};
A C-string needs to be null-terminated (char '\0'). The third cout statement will keep writing out chars until it reaches one (i.e. it will continue into whatever is next in memory).

If you want to see what it is doing change the foo1 definition (or perhaps the foo definition) to
char foo1[6] = "Hiyah";

If you want to fix the problem change your myword statement to
char myword[6] = {'H','e','l','l','o','\0'};

Note that if you want it to be a null-terminated C-string (and that is what you are doing here) then the size of the array needs to be large enough to include that null character.
OK, the terminating character is clear to me, but then I don't get why the compiler of mine (gcc 5.4.0, ubuntu, amd64) doesn't put it out twice, but adds that


sign to the end (seems like it has been destroyed by copy and paste in my post above)?
Last edited on
Shouldn't the compiler add the '\0' to the char array?
When I run the following code on the shell it prints Hello world as expected. http://cpp.sh/7auzi
1
2
3
4
5
6
7
8
#include <iostream>

int main()
{
  char msg[] = "Hello world";
  
  std::cout << msg;
}
Shouldn't the compiler add the '\0' to the char array?

Only if you initialize the array with a string. If you initialize your array with single characters you need to be sure that you add the terminating character if you actually want a string, remember it is perfectly acceptable to have an array of char that is not terminated (not a string).

all the standard C functions for strings maintain the terminal zero. Hands on manipulation or using things like memcpy instead of strcpy won't. string solves the problem by doing it for you as well.

you can also initialize it with

sprintf(msg,"hello world"); //this is more powerful as you can inject variables into the string.
or
strcpy(msg, "hello world"); //less powerful.

all the standard C functions for strings maintain the terminal zero.

No, all the C-string functions require C-strings (terminated arrays of char), if you call the C-string functions without a C-string you invoke undefined behavior.

Maintain = terminal is there going in, the function processes the array, and it returns an array with a correct terminal after. They correctly maintain it. If it isn't there going in, there is nothing to maintain.

this is the answer to


Shouldn't the compiler add the '\0' to the char array?

the compiler does not do anything at all, but if you use the string routines, it maintains the \0 if it was there to begin with. If its not there to begin with, its simply wrong; correct the initializer for the 'string'.

the reason nothing is done for you is that it is perfectly ok to have an array of data as bytes via char data[10000] or whatever. this isnt a string, but its the same syntax, and the compile can't second guess you.
Last edited on
> all the standard C functions for strings maintain the terminal zero.

>> Maintain = terminal is there going in, the function processes the array, and it returns an array with a
>> correct terminal after. They correctly maintain it. If it isn't there going in, there is nothing to maintain.

Not necessarily.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cstring>

int main()
{
    const char srce[] = "hello world!!!" ;
    char dest[8] = "fine!!\n" ; 

    std::cout << sizeof(dest) << ' ' << std::strlen(dest) << ' ' << dest << '\n' ; // fine (dest is null terminated)

    // dest is null terminated "going in" (though this is not required by std::strncpy)
    std::strncpy( dest, srce, sizeof(dest) ) ;
    // dest is not null terminated "coming out" (the null terminator is not maintained)

    // microsoft: *** warning: The prior call to 'strncpy' might not zero-terminate string 'dest'.
    // (note that null-terminating dest would have been a gross violation of both the C and the C++ standards)
    // undefined behaviour (dest is not null terminated)
    // for instance, strlen(dest) may return a value greater than the entire size of the array
    std::cout << sizeof(dest) << ' ' << std::strlen(dest) << ' ' << dest << '\n' ; 
}

http://rextester.com/IQEP26266
That's what I have been confused about as well because I got "Hello World", followed by an extra character I can't explain myself :-)
> followed by an extra character I can't explain myself :-)

It is undefined behaviour.
"Undefined behaviour: Renders the entire program meaningless ..." http://en.cppreference.com/w/cpp/language/ub
Ah! Thanks ;-) I see, I never stop learning :-D
Topic archived. No new replies allowed.