c - 为什么二维数组可以从 int ** 转换为 int * ,而指针数组却不能

标签 c arrays pointers casting int

#include <stdio.h>
#include <string.h>
int main(void)
{
    int arr2d[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
    int* arr = (int*)arr2d;
    int i = 0;
    for (i = 0; i < 9; i++)
    {
        printf("%d ", arr[i]);
    }

    printf("\n\n");
    int arr1[] = { 11,12 };
    int arr2[] = {13, 14, 15, 16};
    int arr3[] = { 17, 18, 19 };
    int * parr[3] = { arr1,arr2,arr3 };
    int *parr1 = (int*)parr;
    for (i = 0; i < 9; i++)
    {
        printf("%d ", parr1[i]);
    }
    return 0;

一开始我从二维数组转换并打印它,但之后我用指针数组进行转换,但它不起作用,有人可以解释一下吗?

最佳答案

您可能想了解这些对象在内存中的布局:

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

这会在内存(本例中为堆栈)中创建一个 int[][3] 类型的对象 array,该对象以假设的(16 位字大小)物理布局)架构为:

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

其中0x8000表示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;

这里array_pointers的类型是int *[],这意味着它是一个指向int数组的指针。内存布局如下:

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

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

因此,当您尝试打印 array_pointers2 的内容(现在包含指向 int 数组的指针)时,您将打印地址值而不是它们指向的数字到。

这是一个输出这些对象的内存地址的示例:

https://ideone.com/T52Ow0

打印内容:

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

在我的电脑上。

外部链接过期时的源代码:

#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;
}

关于c - 为什么二维数组可以从 int ** 转换为 int * ,而指针数组却不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49954102/

相关文章:

arrays - Swift:使用备用键的合并排序算法

objective-c - 将对象传递给未分配的指针

c - 我如何概括这个我用来指定 vector 长度的宏?

c++ - HTTP 发送对 OPTIONS 请求的响应 [C]

c - 如何检查它是否是数字并在不是数字时重复

c - 如何通过指针迭代二维数组?

c - 有关于 C 结构顺序的任何保证吗?

c - 如何将真实文件夹添加到我的 Netbeans C 项目中?

JavaScript 将一个数组与另一个数组匹配?

c - C 中将字符数组拆分为多个较小的以空结尾的字符数组