[Solved] Are the elements of an array saved continuously in memory?


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 typechar [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?