Home > Enterprise >  What happens when running (int *)"some string"
What happens when running (int *)"some string"

Time:01-07

I'm learning the pointer nowadays and I find there is a code on the book

std::cout << (int *)"Home of the jolly bytes";

I run it and it print the

0x55c064d9b005

that seem like something's address and I want to know what did it print, so I use "*" try to check its value at that address and convert it to char and foud it's "H".

std::cout << (char)*(int *)"Home of the jolly bytes";
//output: H

I know that "typename*" creats a pointer points to the typename data, but what happened when running this code?

CodePudding user response:

"text" is a string literal. Strings are arrays of char objects.

(T)expression is an explicit conversion of the expression to the type T.

std::cout << expression inserts the right hand operand to the standard output stream.

In the expression (int *)"Home of the jolly bytes" there is an implicit conversion from the array to type const char* which is a pointer. It points to the first element of the array. That type is then reinterpreted as int* due to the explicit conversion. You should avoid using such C-style casts in favour of using C style casts such as static_cast etc. You should also avoid reinterpreting pointers to unrelated types without knowing what that does.

Inserting an int* into a character stream will invoke the overload of the insertion operator that accepts a void* parameter. This conversion is implicit. The behaviour is to print a textual representation of the address that the pointer points to. It is a number in hexadecimal radix.

*(int *)"Home of the jolly bytes" in this expression, the left most * is the indirection operator. It indirects through the pointer that is the operand. The result is an lvalue referring to the pointed object. However, in this case the behaviour of the program is undefined because the type of the reinterpreted pointer doesn't match the type of the pointed object. Don't do this.

CodePudding user response:

On this statement:

std::cout << (int *)"Home of the jolly bytes";

It is indeed printing the starting address of the characters in the string literal. A string literal is a const char[N] array (in this case, N=24), and an array decays into a pointer to its 1st element.

std::istream does not have any operator<< that accepts an int* pointer, but it does have one that accepts a char* pointer to print a null-terminated string, and one that accepts a void* pointer to print the address being pointed at.

int* is implicitly convertible to void*, so the code is printing the address of the string literal, rather than printing its contents. But, it is unusual to cast a char* pointer to an int* in this situation, void* would make more sense, eg:

std::cout << (const void *)"Home of the jolly bytes";

In any case, on this statement:

std::cout << (char)*(int *)"Home of the jolly bytes";

It is reinterpreting the starting address of the characters as-if it were the starting address of an int instead. Thus, dereferencing that int* pointer will read the 1st 4 characters together as a single int value (assuming char is 8 bits in size, and int is 32 bits in size):

--------------------------------------------------------------------------------------------
| H | o | m | e |   | o | f |   | t | h | e |   | j | o | l | l | y |   | b | y | t | e| s |
--------------------------------------------------------------------------------------------
|___|
  |
  char*

|_______________|
       |
       int*

Thus, the dereferenced int will consist of these bytes in memory:

        H    o    m    e
*int = 0x48 0x6F 0x6D 0x65

The code is then truncating that int value to a 1-byte char value.

On a little-endian system, that will yield the value of the H character:

        H    o    m    e
*int = 0x48 0x6F 0x6D 0x65
     = 0x656D6F48 (decimal 1701670728)
     =       0x48 when truncated to char

On a big-endian system, it will yield the value of the e character instead:

        H    o    m    e
*int = 0x48 0x6F 0x6D 0x65
     = 0x486F6D65 (decimal 1215262053)
     =       0x65 when truncated to char

CodePudding user response:

A conversion from one pointer type to another pointer type does exactly nothing on a typical contemporary system, an x86 of any kind, because all pointers have the same "representation" (they use the same number of bytes to store an address and the same values for the same address).

What does change is what code the compiler emits for operations on pointers with different types, specifically by how much adding one increments the numeric value (e.g. 1 for char, 4 for int) and how much of that memory is read resp. used when it is loaded into a register.

When you dereference a pointer with *or by indexing the resulting expression will have the appropriate type (e.g. int or char) and will, for instance when you output it, invoke the proper function overloads.

  •  Tags:  
  • Related