char sentence[] ={'k','k','k','k','k','k','k','k'}; (8 character)
std::cout << sentence << std::endl;
Then output just "kkkkkkkk".
But if we decrement characters of array (i.e. preceding array have 8 character after less 8 character)
char sentence[] ={'k','k','k','k','k','k','k'}; ( 7 character)
std::cout << sentence << std::endl;
output:
kkkkkkk`\363\277\357\376.
The operand sentence decays to a pointer to first element of the array. The stream insertion operator overload that accepts const char* parameter requires that the pointer is to a null terminated array. If that pre-condition is violated, then the behaviour of the program is undefined.
sentence does not contain the null terminator character. You insert it into a character stream. The behaviour of the program is undefined.
Then output just "kkkkkkkk".
That's one potential behaviour. This behaviour isn't guaranteed because the behaviour of the program is undefined.
But if we decrement length of array then output kkkkkkk`\363\277\357\376.
That's one potential behaviour. This behaviour isn't guaranteed because the behaviour of the program is undefined.
char arrays are often used for null-terminated strings, but not always.
When you write
const char* str = "Hello";
then str is a pointer to the first element of a const char[6]. 5 for the characters, and the rules of the language make sure that there is room for the terminating \0.
On the other hand, sometimes a char array is just that: An array of characters. When you write
char sentence[] ={'H','e','l','l','o'};
Then sentence is an array of only 5 chars. It is not a null-terminated string.
This two worlds (general char array / null-terminated strings) clash when you call
std::cout << sentence << std::endl;
because the operator<< overload does expect a null-terminated string. Because sentence does not point to a null-terminated string, your code has undefined behavior.
If you want sentence to be a string, make it one:
char sentence[] = {'H','e','l','l','o','\0'};
Or treat it like a plain array of characters:
for (const auto& c : sentence) {
std::cout << c;
}
Try using
char sentence[] = {'k','k','k','k','k','k','k','k','\0'};
you must always use a '\0' at the end when you are declaring a char array manually and want to print it. Because either cout or printf function will look for '\0' character and will only stop printing if it finds '\0'. also make sure you wont you it in middle of your array as it wont print the complete array
Related
char sentence[] ={'k','k','k','k','k','k','k','k'}; (8 character)
std::cout << sentence << std::endl;
Then output just "kkkkkkkk".
But if we decrement characters of array (i.e. preceding array have 8 character after less 8 character)
char sentence[] ={'k','k','k','k','k','k','k'}; ( 7 character)
std::cout << sentence << std::endl;
output:
kkkkkkk`\363\277\357\376.
The operand sentence decays to a pointer to first element of the array. The stream insertion operator overload that accepts const char* parameter requires that the pointer is to a null terminated array. If that pre-condition is violated, then the behaviour of the program is undefined.
sentence does not contain the null terminator character. You insert it into a character stream. The behaviour of the program is undefined.
Then output just "kkkkkkkk".
That's one potential behaviour. This behaviour isn't guaranteed because the behaviour of the program is undefined.
But if we decrement length of array then output kkkkkkk`\363\277\357\376.
That's one potential behaviour. This behaviour isn't guaranteed because the behaviour of the program is undefined.
char arrays are often used for null-terminated strings, but not always.
When you write
const char* str = "Hello";
then str is a pointer to the first element of a const char[6]. 5 for the characters, and the rules of the language make sure that there is room for the terminating \0.
On the other hand, sometimes a char array is just that: An array of characters. When you write
char sentence[] ={'H','e','l','l','o'};
Then sentence is an array of only 5 chars. It is not a null-terminated string.
This two worlds (general char array / null-terminated strings) clash when you call
std::cout << sentence << std::endl;
because the operator<< overload does expect a null-terminated string. Because sentence does not point to a null-terminated string, your code has undefined behavior.
If you want sentence to be a string, make it one:
char sentence[] = {'H','e','l','l','o','\0'};
Or treat it like a plain array of characters:
for (const auto& c : sentence) {
std::cout << c;
}
Try using
char sentence[] = {'k','k','k','k','k','k','k','k','\0'};
you must always use a '\0' at the end when you are declaring a char array manually and want to print it. Because either cout or printf function will look for '\0' character and will only stop printing if it finds '\0'. also make sure you wont you it in middle of your array as it wont print the complete array
When I was trying to cout them
char l[] {'t', 'r', 'y'};
std::cout << l << std::endl;
I got try printed in the terminal.
However, when I tried this.
char l[] {'try'};
I only got y.
I came to c++ from python so lots of things don't make sense to me, so can you explain the difference of these two expressions?
None of your examples are valid.
The first one has undefined behavior.
char l[] {'t', 'r', 'y'};
std::cout << l << std::endl;
Here you define l to be a char[3]. That's fine. Printing it like you do is however not since the operator<< overload you use requires a null terminated string. Your char[3] is not null terminated so the operator<< overload will try to find the null terminator out of bounds which causes undefined behavior. A working variant would have been
char l[] {'t', 'r', 'y', '\0'};
which would have made it a char[4] with a \0 (null terminator) at the end.
The second example tries to create the array from a multibyte character. Single quotes are for individual characters so that's why that interpretation doesn't work. Many compilers will simply refuse to compile it. To create the array from a string literal, use double quotes:
char l[] {"try"};
or the idiomatic way:
char l[] = "try";
Both versions will create a null terminated array, just like char l[] {'t', 'r', 'y', '\0'};
char l[] {'t', 'r', 'y'}; defines l to be array of three characters with no terminating null character, so using it in std::cout << l is bad because the insert operator << needs the terminating null character to tell it where the end is.
char l[] {'try'}; defines l to be an array of one character because 'try' is a single number formed from three characters in an implementation-defined way. Since it is only one number, the size of the array l is set to be one element. To initialize l with that number, it is converted to char, which loses information about the three characters.
char l[] {"try"}; would define l to be an array of four characters, because string literals (marked by " instead of ') automatically include a terminating null character. Also, even though a string literal is “one thing,” there is a special rule that says when a string literal is used to initialize an array, its contents are used to initialize the array. So the array size is four elements because there are four characters in the string.
In this declaration
char l[] {'t', 'r', 'y'};
there is declared a character array that contains exactly three characters. As the array does not contain a string (a sequence of characters terminated with the zero or the so-called null character '\0') then the next statement
std::cout << l << std::endl;
invokes undefined behavior because in this case the operator << expects a pointer to a string (an array designator with rare exceptions is converted to pointer to its first element).
Instead you could write for example
std::cout.write( l, sizeof( l ) ) << std::endl;
Otherwise you could initialize the array by a string literal like
char l[] {"try"};
and write
std::cout << l << std::endl;
In this declaration
char l[] {'try'};
there is declared a character array that is initialized by the multicharacter literal 'try' that has an implementation defined value and the type int. Multicharacter literals are conditionally supported.
The compiler should issue a message for such a declaration that there is used a narrowing conversion from int to char.
Again you may not write
std::cout << l << std::endl;
because the array does not contain a string. It contains only one element with an implementation defined value.
Try this code snippet
char l[]{ 'try' };
std::cout << sizeof( l ) << '\n';
To output the array you could write as already shown above
std::cout.write( l, sizeof( l ) ) << std::endl;
When you insert an array into an output stream, the array argument implicitly converts to a pointer to char. When you pass a pointer to char into an output stream, it must point to a null terminated string of characters. If the pointer is not to a null terminated character string, then the behaviour of the program is undefined. Undefined behaviour should be avoided.
char l[] {'t', 'r', 'y'};
std::cout << l << std::endl;
l is an array of 3 characters that does not contain a null terminator character. In this example you insert a pointer to non-null terminated string into an output stream and the behaviour of the program is undefined. The program is broken. Don't do this.
char l[] {'try'};
l is an array of 1 character that does not contain a null terminator character. If you insert this array to an output stream, then the behaviour of the program is undefined. The program is broken. Don't do this.
Note: 'try' is a multicharacter literal. It's type is int and its value is implementation defined. Multicharacter literals aren't useful very often. What you probably intended to do, is to use a string literal:
char l[] = "try";
The string literal "try" is an array of 4 characters; ending in the null terminator character.
When i cast a char var. using this operator "&"( i really have to cast it to write it in a char [] to write it in a file as a fixed length record ) the casted value is the char concatenated to the char [] which i wrote in the input console after it . (if the next attribute was not char [] no thing happens and it does not overlaps only if it is a char [] it overlaps) . Because of that prob. i can not maintain that records are written correctly . Anyone know why this prob. happens? Thanks in advance .
I have tried to search and found that casting char to ((char*)&) is not safe . but i still can not understand how casting process used the char [] attribute after it in the console of input
The code that refers to the problem:
struct citizen
{
char gender ;
char name [10] ;
};
istream& operator>>(istream& in, citizen& c)
{
in >>c.gender ; // input f
in>>c.name ; // iput mariam
cout<<c.gender ; // outputs "f"
cout<<(char*)&c.gender; // outputs " fmariam"
return in ;
}
The stream insertion operator requires that a char* inserted into the stream points to an array of characters terminated by the null-character.
char gender is not a null-teminated array of characters (unless the value happens to be the null-terminator, in which case it can be treated as an array of one characters representing an empty string as far as pointer arithmetic is concerned).
By inserting the non-null-terminated char* into the stream, you violate the requirement mentioned above, and as a result, the behaviour of your program is undefined.
why this prob. happens?
Because the behaviour of your program is undefined.
The << operator for cout depends on the type of its argument. c.gender is a type char, so cout outputs its character value. &c.gender is the address of a char... analogous to a char * (so your cast doesn't do anything). As a char *, cout<< interprets the reference as an array of characters, terminated with a '\0' character, aka a "nul terminated string." Since the fields of the struct are packed, cout doesn't see a '\0' until the end of the array of characters adjacent to the gender field.
You're kinda lucky your program didn't crash.
This might be a stupid question, but I'm new to C++ so I'm still fooling around with the basics. Testing pointers, I bumped into something that didn't produce the output I expected.
When I ran the following:
char r ('m');
cout << r << endl;
cout << &r << endl;
cout << (void*)&r << endl;
I expected this:
m
0042FC0F
0042FC0F
..but I got this:
m
m╠╠╠╠ôNh│hⁿB
0042FC0F
I was thinking that perhaps since r is of type char, cout would interpret &r as a char* and [for some reason] output the pointer value - the bytes comprising the address of r - as a series of chars, but then why would the first one would be m, the content of the address pointed to, rather than the char representation of the first byte of the pointer address.. It was as if cout interprets &r as r but instead of just outputting 'm', it goes on to output more chars - interpreted from the byte values of the subsequent 11 memory addresses.. Why? And why 11?
I'm using MSVC++ (Visual Studio 2013) on 64 bit Win7.
Postscript: I got a lot of correct answers here (as expected, given the trivial nature of the question). Since I can only accept one, I made it the first one I saw. But thanks, everyone.
So to summarize and expand on the instinctive theories mentioned in my question:
Yes, cout does interpret &r as char*, but since char* is a 'special thing' in C++ that essentially means a null terminated string (rather than a pointer [to a single char]), cout will attempt to print out that string by outputting chars (interpreted from the byte contents of the memory address of r onwards) until it encounters '\0'. Which explains the 11 extra characters (it just coincidentally took 11 more bytes to hit that NUL).
And for completeness - the same code, but with int instead of char, performs as expected:
int s (3);
cout << s << endl;
cout << &s << endl;
cout << (void*)&s << endl;
Produces:
3
002AF940
002AF940
A char * is a special thing in C++, inherited from C. It is, in most circumstances, a C-style string. It is supposed to point to an array of chars, terminated with a 0 (a NUL character, '\0').
So it tries to print this, following on in to the memory after the 'm', looking for a terminating '\0'. This makes it print some random garbage. This is known as Undefined Behaviour.
There is an operator<< overload specifically for char* strings. This outputs the null-terminated string, not the address. Since the pointer you're passing this overload isn't a null-terminated string, you also get Undefined Behavior when operator<< runs past the end of the buffer.
Conversely, the void* overload will print the address.
Because operator<< is overloaded based on the data type.
If you give it a char, it assumes you want that character.
If you give it a void*, it assumes you want an address.
However, if you give it a char*, it takes that as a C-style string and attempts to output it as such. Since the original intent of C++ was "C with classes", handling of C-style strings was a necessity.
The reason you get all the rubbish at the end is simply because, despite your assertion to the compiler, it isn't actually a C-style string. Specifically, it is not guaranteed to have a string-terminating NUL character at the end so the output routines will just output whatever happens to be in memory after it.
This may work (if there's a NUL there), it may print gibberish (if there's a NUL nearby), or it may fall over spectacularly (if there's no NUL before it gets to memory it cannot read). It's not something you should rely on.
Because there's an overload of operator<< which takes a const char pointer as it's second argument and prints out a string. The overload that takes a void pointer prints only the address.
A char * is often - usually even - a pointer to a C-style null-terminated string (or a string literal) and is treated as such by ostreams. A void * by contrast unambiguously indicates a pointer value is required.
The output operator (operator<<()) is overloaded for char const* and void const*. When passing a char* the overload for char const* is a better match and chosen. This overload expects a pointer to the start of a null terminated string. You give it a pointer to an individual char, i.e., you get undefined behavior.
If you want to try with a well-defined example you can use
char s[] = { 'm', 0 };
std::cout << s[0] << '\n';
std::cout << &s[0] << '\n';
std::cout << static_cast<void*>(&s[0]) << '\n';
//if the code is
char str[]="hello";
char *sptr=&str[2];
cout<<sptr;
//the output is not a hexadecimal value but llo
....why?
//also consider the following code
char array[]="hello world";
char array1[11];
int i=0;
while(array[i]!='\0')
{array1[i]=array[i];
i++;}
//if we print array1,it is printed as hello world, but it should have stopped when the space between hello and world is encountered.
The operator<< overload used by output streams is overloaded for const char* so that you can output string literals and C strings more naturally.
If you want to print the address, you can cast the pointer to const void*:
std::cout << static_cast<const void*>(sptr);
In your second problem, \0 is the null terminator character: it is used to terminate the string. array actually contains "hello world\0", so the loop doesn't stop until it reaches the end of the string. The character between hello and world is the space character (presumably): ' '.
When you print a char*, it's printed as a string.
'\0' is not ' '
Regarding your first question:
By default, a char is interpreted as its textual representation trough a call to std::cout.
If you want to output the hexadecimal representation of your character, use the following code:
std::cout << std::hex << static_cast<int>(c);
Where c is your character.
In your code:
cout<<sptr;
sptr is a pointer to a char, not a char so std::cout displays it as a C-string.
Regarding your second question:
A space is the ASCII character 32, not 0. Thus your test just checks for the ending null character for its copy.
With regards to cout, there is a special overload for writing const char * (and char *) to streams that will print the contents rather than the pointer.
With regards to array1, actually there is nothing wrong with making it size 11 as you do not copy the null byte into it. The issue comes though when you try printing it, as it will try to print until it finds a 0 byte and that means reading off the end of the array.
As it stands the compiler may well pad out a few bytes because the next thing that follows is an int so it is likely to align it. What is actually in that one byte of padding could be anything though, not necessarily a zero character.
The next few characters it is likely to meet will be the int itself, and depending on the endian-ness the zero byte will be either the first or second.
It is technically undefined behaviour though.