gpt4 book ai didi

c - 指向分配给二维数组的指针的指针,指向错误的地址

转载 作者:太空狗 更新时间:2023-10-29 16:07:34 24 4
gpt4 key购买 nike

我是 C 的新手,虽然我认为我几乎了解了有关指针和数组的全部逻辑,但我遇到了一个对我来说没有任何意义的问题。

考虑一个二维数组,比如说

double arr[][3] = { {1,2,3}, {4,5,6} };

和一个指向指针的指针

double ** ptrptr;

现在,假设打印arrarr[0] 分别指向的地址,即

printf( "%ld \n", (long) arr);
printf( "%ld \n", (long) *arr);

产生类似的东西

140734902565640
140734902565640

因为 arr(数组的数组)的第一个元素和 *arr( double 组)的第一个元素具有相同的位置。到目前为止,一切都很好。现在我的问题:

我这样做:

ptrptr = (double **) arr;
printf( "%ld \n", (long) ptrptr);
printf( "%ld \n", (long) *ptrptr);

我希望得到与以前相同的输出,但相反我得到的是

140734902565640
4607182418800017408

所以看起来 ptrptrarr 都评估为指向同一位置的指针 - 正如预期的那样 - 但是 *ptrptr*arr 。为什么?
此外,如果我再次取消引用,即 **ptrptr,我会遇到段错误。

我的逻辑是……像这样,松散地说:
ptrptr == arr == &arr[0] 应该指向
*ptrptr == *arr == arr[0] == &arr[0][0] 又应该指向
**ptrptr == *arr[0] == arr[0][0]

虽然我找到了一个可以满足我的目的的解决方法,但我仍然很想知道为什么这不起作用。

最佳答案

让我们谈谈表达式类型

除非它是 sizeof 或一元 & 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,类型的表达式“T 的 N 元素数组”被转换(“衰减”)为“指向 T 的指针”类型的表达式,表达式的值是数组的第一个元素。

表达式 arr 的类型为“double 的 3 元素数组的 2 元素数组”。在行中

printf( "%ld \n", (long) arr);

arr 不是 &sizeof 运算符的操作数,因此它被转换为“指向 3- 的指针”类型的表达式double”的元素数组,其值为第一个元素的地址,即&arr[0]

行内

printf( "%ld \n", (long) *arr);

由于表达式 arr 的类型为“指向 double 的 3 元素数组的指针”,表达式 *arr(相当于表达式 arr[0]) 的类型为“double 的三元素数组”。由于此表达式不是 sizeof 或一元 & 运算符的操作数,因此它被转换为“指向 double 的指针”类型的表达式,其值为第一个元素的地址,即&arr[0][0]

在 C 中,数组的地址与数组的第一个元素的地址相同(没有为指向第一个元素的指针预留单独的存储;它是从数组表达式本身计算的)。该数组在内存中的布局为


+---+
arr: | 1 | 0x0x7fffe59a6ae0
+---+
| 2 | 0x0x7fffe59a6ae8
+---+
| 3 | 0x0x7fffe59a6aec
+---+
| 4 | 0x0x7fffe59a6af0
+---+
| 5 | 0x0x7fffe59a6af8
+---+
| 6 | 0x0x7fffe59a6afc
+---+

所以下面的表达式都会产生相同的,但是类型会不同:

Expression            Type                Decays to     
---------- ---- ---------
arr double [2][3] double (*)[3]
&arr double (*)[2][3] n/a
*arr double [3] double *
arr[i] double [3] double *
&arr[i] double (*)[3] n/a

*arr[i]arr[i][j] 都产生一个 double 值。

现在让我们看看ptrptr:

double **ptrptr = (double **) arr;
printf( "%ld \n", (long) ptrptr);
printf( "%ld \n", (long) *ptrptr);

我们注意到的第一件事是 ptrptr 不是数组表达式,因此上面的转换规则不适用。我们将它指定为指向 arr 的第一个元素,但之后它的行为与任何其他指针一样,因此表达式 ptrptr*ptrptr 具有不同的值。由于 ptrptr 指向数组的第一个元素 (&arr[0][0]),*ptrptr 产生 value 存储在第一个元素,即 1.00。碰巧的是,当您将 1.00 的位模式解释为该特定平台上的长整数时,它会显示为 4607182418800017408。

下面是一些代码,可以使上面的内容更加清晰:

#include <stdio.h>

int main( void )
{
double arr[][3] = {{1,2,3},{4,5,6}};
double **ptrptr = (double **) arr;

printf( " arr: %p\n", (void *) arr );
printf( " &arr: %p\n", (void *) &arr );
printf( " *arr: %p\n", (void *) *arr );
printf( " arr[0]: %p\n", (void *) arr[0] );
printf( "&arr[0]: %p\n", (void *) &arr[0] );

printf( " ptrptr: %p\n", (void *) ptrptr );
printf( "*ptrptr: %p (%f %ld)\n", (void *) *ptrptr,
*(double *) ptrptr, *(long int *) ptrptr );

return 0;
}

这是输出:

    arr: 0x7fffe59a6ae0
&arr: 0x7fffe59a6ae0
*arr: 0x7fffe59a6ae0
arr[0]: 0x7fffe59a6ae0
&arr[0]: 0x7fffe59a6ae0
ptrptr: 0x7fffe59a6ae0
*ptrptr: 0x3ff0000000000000 (1.000000 4607182418800017408)

同样,*ptrptr 为我们提供了数组第一个元素的值,即 1.0,但我们将该位模式解释为指针值 ( 0x3ff0000000000000) 和一个长整数 (4607182418800017408)。

关于c - 指向分配给二维数组的指针的指针,指向错误的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21565036/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com