The weird thing with C ++ memory management

Consider the output of this code:

char A = 'a'; char B[] = "b"; cout<<&A; 

It outputs "ab" (concatenation of A and B ), and I wonder why. Please explain this to me.

+5
source share
7 answers

Because &A is char * . The string represented by char * must have a trailing byte of '\0' .

&A points to one char , without the next '\0' . Thus, attempting to print this text string results in undefined behavior.

+15
source

You got an unexpected result, because operator << for objects of type char * overloaded in such a way that it displays the lines pointed to by pointers of type char * .

It seems that your compiler placed the array B after the character A , and in memory they looked like a single line.

 'a' 'b' '\0' | | AB 

(It is not specified in the C ++ standard whether A B precedes or B precedes A in memory and whether there will be a gap due to byte filling between objects.)

If you want to display the address of object A, you must write, for example,

 cout<< ( void * )&A; 

or

 cout<< ( const void * )&A; 

or either for example

 cout<< static_cast<void *>( &A ); 

or how

 cout<< static_cast<const void *>( &A ); 

It doesn't matter if the const specifier is specified for a pointer to a mutable object, because. It will be implicitly converted to type const void * in the statement

 basic_ostream<charT,traits>& operator<<(const void* p); 
+4
source

I wonder why

Since the thread insertion operator requires that any character pointer passed to it point to a character string with a null terminating character. The pointer passed to cout points to A , which is not a null-terminated character string. Because the preconditions (requirements) of the operation were not met, the behavior is undefined.


There are two relevant overloads for the insert operator (I simplified the details of the template and the fact that one of them is member overload and the other is not):

 ostream& operator<< (const void*); ostream& operator<< (const char*); 

All other pointers are implicitly converted to void* and use the same overload, and the pointer is displayed as a memory address. But the latter prefers overloading for character pointers, and the argument should be an empty terminating string.

So, since a character pointer is interpreted as a null-terminated string, a naive attempt to print the address of a character does not work. Solution: direct pointer to void* before passing to stream.

Streams were designed to conveniently support null-terminated strings, such as string literals, which were considered (and) streams more typically than addresses. For example, it is convenient that std::cout << "Hello World!"; . Prints "Hello World" instead of the memory address where the string literal is located.

+1
source

cout expects the char* parameter to point to a null-terminated string. But &A does not end in zero, so the precondition fails, and this leads to undefined behavior.

Undefined behavior cannot be explained, because the standard allows something to happen. Displaying a few more characters is one of the possible results. How crumbling. Or something else.

+1
source

This is compiler dependent behavior. Often A nad B will stand out one after another on the stack. Taking address A will look like a null-terminated string "ab". Do not do this! You rely on the layout of the stack frame that the compiler creates.

0
source

because your char is not terminated by zero. The behavior for this will be UNDEFINED.

0
source

Your compiler placed a line containing "b" and "\ 0" immediately after the character "a", and after you typed your character A as the line on which it found "a", and then 'b', for followed by '\ 0', so you typed 'ab'

0
source

Source: https://habr.com/ru/post/1014149/


All Articles