[Solved] Why can I convert from int ** to int * in the case of the two-dimensional array, but not in the case of the array of pointers


You might want to learn how these objects are laid out in memory:

int array[][3] = { {1,2,3}, {4,5,6}, {7,8,9} };
int *p_array = (int *) array;

This creates an object array of type int[][3] in memory (in this case stack) physically laid out in a hypothetical (16-bit word size) architecture as:

  array 0x8000: 0x0001
        0x8002: 0x0002
        0x8004: 0x0003
        0x8006: 0x0004
        0x8008: 0x0005
        0x800A: 0x0006
        0x800C: 0x0007
        0x800E: 0x0008
        0x8010: 0x0009
p_array 0x8012: 0x8000

Where 0x8000 denotes the imaginary stack address of array.

However, in your second example:

int array1[] = { 11, 12 };
int array2[] = { 13, 14, 15, 16 };
int array3[] = { 17, 18, 19 };
int *array_pointers[] = { array1, array2, array3 };

int *array_pointers2 = (int*) array_pointers;

Here array_pointers is of type int *[] which means it is a pointer to array of ints. And the memory layout would be like the following:

array1 0x8000: 0x000B
       0x8002: 0x000C
array2 0x8004: 0x000D
       0x8006: 0x000E
       0x8008: 0x000F
       0x800A: 0x0010
array3 0x800C: 0x0011
       0x800E: 0x0012
       0x8010: 0x0013

and

array_pointers:  0x8012: 0x8000 address of array1
                 0x8014: 0x8004 address of array2
                 0x8016: 0x800C address of array3
array_pointers2: 0x8018: 0x8012 address of array_pointers

So when you try to print the contents of array_pointers2, which now contain pointers to array of ints, you will print the address values rather than the numbers they point to.

Here is an example that outputs the memory address of those objects:

https://ideone.com/T52Ow0

Which prints:

array      0x7ffeda682090: 0x00000000000001
           0x7ffeda682094: 0x00000000000002
           0x7ffeda682098: 0x00000000000003
           0x7ffeda68209c: 0x00000000000004
           0x7ffeda6820a0: 0x00000000000005
           0x7ffeda6820a4: 0x00000000000006
           0x7ffeda6820a8: 0x00000000000007
           0x7ffeda6820ac: 0x00000000000008
           0x7ffeda6820b0: 0x00000000000009
p_array    0x7ffeda682038: 0x007ffeda682090

array1     0x7ffeda68204c: 0x0000000000000b
           0x7ffeda682050: 0x0000000000000c
array2     0x7ffeda682060: 0x0000000000000d
           0x7ffeda682064: 0x0000000000000e
           0x7ffeda682068: 0x0000000000000f
           0x7ffeda68206c: 0x00000000000010
array3     0x7ffeda682054: 0x00000000000011
           0x7ffeda682058: 0x00000000000012
           0x7ffeda68205c: 0x00000000000013
array_poin 0x7ffeda682070: 0x007ffeda68204c
           0x7ffeda682078: 0x007ffeda682060
           0x7ffeda682080: 0x007ffeda682054
array_poi2 0x7ffeda682040: 0x007ffeda682070

on my computer.

Source code for that in case external link expires:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int array[][3] = { {1,2,3}, {4,5,6}, {7,8,9} };
    int *p_array = (int*) array;

    for (int i = 0; i < 9; i++) {
        printf("%-10s %08p: %016p\n", i == 0 ? "array" : "", &p_array[i], p_array[i]);
    }

    printf("%-10s %08p: %016p\n", "p_array", &p_array, p_array);

    int array1[] = { 11, 12 };
    int array2[] = { 13, 14, 15, 16 };
    int array3[] = { 17, 18, 19 };

    int *array_pointers[] = { array1, array2, array3 };
    int *array_pointers2 = (int*) array_pointers;

    putchar('\n');

    for (int i = 0; i < sizeof(array1) / sizeof(array1[0]); i++) {
        printf("%-10s %08p: %016p\n", i == 0 ? "array1" : "", &array1[i], array1[i]);
    }

    for (int i = 0; i < sizeof(array2) / sizeof(array2[0]); i++) {
        printf("%-10s %08p: %016p\n", i == 0 ? "array2" : "", &array2[i], array2[i]);
    }

    for (int i = 0; i < sizeof(array3) / sizeof(array3[0]); i++) {
        printf("%-10s %08p: %016p\n", i == 0 ? "array3" : "", &array3[i], array3[i]);
    }

    for (int i = 0; i < sizeof(array_pointers) / sizeof(array_pointers[0]); i++) {
        printf("%-10s %08p: %016p\n", i == 0 ? "array_poin" : "", &array_pointers[i], array_pointers[i]);
    }

    printf("%-10s %08p: %016p\n", "array_poi2", &array_pointers2, array_pointers2);

    return 0;
}

solved Why can I convert from int ** to int * in the case of the two-dimensional array, but not in the case of the array of pointers