According to the C++ Standard (8.3.4 Arrays)
1…An object of array type contains a contiguously allocated non-empty set
of N subobjects of type T.
Applying to the array definition from your post it means only that four pointers (the elements of the array) to string literals are allocated in contiguous extent of memory. This extent of memory does not include the string literals themselves.
In C++ string literals have types of constant character arrays. When they are used as initializers like this
char* names[4] = {"James", "Dustin", "Rich", "Ed"};
then they are implicitly converted to pointers of type const char *
that point to the first elements of the arrays.
So it would be better to define the array like
const char* names[4] = {"James", "Dustin", "Rich", "Ed"};
If you want to output the third element of the array (take into account that it is a pointer) then you have to write
std::cout << ( const void * ) ( names + 2 ) << std::endl;
If you want to output the string literal that is pointed to by this element you should write simply
std::cout << *( names + 2 ) << std::endl;
As for expression
*(char**)((char*)names+2*sizeof(char*))
then subexpression (char*)names
reinterprets the array of type char *[4] like an array pf type
char [4 * sizeof( char * )]. So expression
(char*)names+2*sizeof(char*)
yields the same value as expression
( names + 2 )
For example statements
std::cout << ( const void * )( names + 2 ) << std::endl;
and
std::cout << ( void * )( (char*)names + 2*sizeof(char*) ) << std::endl;
will produce the same output
I think if to run this demonstrative program it will be more clear
#include <iostream>
int main()
{
const char* names[4] = {"James", "Dustin", "Rich", "Ed"};
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )( names + i ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )*( names + i ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )( ( char * )names + i * sizeof( char * ) ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )*( ( const char ** )( ( const char * )names + i * sizeof( char * ) ) ) << std::endl;
}
std::cout << std::endl;
}
The program output might look like
0x7fffc0f639f0
0x7fffc0f639f8
0x7fffc0f63a00
0x7fffc0f63a08
0x40d884
0x40d88a
0x40d891
0x40d896
0x7fffc0f639f0
0x7fffc0f639f8
0x7fffc0f63a00
0x7fffc0f63a08
0x40d884
0x40d88a
0x40d891
0x40d896
In this program expressions ( names + 0 )
, ( names + 1 )
, ( names + 2 )
, ( names + 3 )
are addresses of correspondingly elements of array names with indices 0, 1, 2, 3
.
Expressions *( names + 0 )
, *( names + 1 )
, *( names + 2 )
, *( names + 3 )
are the values stored in this elements.
Expressions ( char * )names + i * sizeof( char * )
where i in the range 0-3
are the same addresses of the array elements. And expressions
*( ( const char ** )( ( const char * )names + i * sizeof( char * ) ) ) give the same values of the elements of the array.
7
solved Are the elements of an array saved continuously in memory?