指向二维数组访问冲突的指针

pointer to two-Dimension array access conflict

提问人:Hossam Ahmed 提问时间:10/17/2023 最后编辑:Vlad from MoscowHossam Ahmed 更新时间:10/17/2023 访问量:69

问:

#include <stdio.h>
int main()
{
   int arr_2D[3][3]={ {1,2,3},
                      {11,22,33},
                      {111,222,333} };
    int (*ptr)[3]=arr_2D;
    
    printf("ptr=0x%0X\n",ptr+1); // ptr=0x60FEE4
    
    printf("*(ptr)=0x%0X\n",*(ptr+1)); //*(ptr+1)=0x60FEE4
    return 0;
}

我尝试使用取消引用运算符访问存储在 (ptr+1) 中的位置 * 为什么 ptr+1 的输出等于 *(ptr+1) 的输出?`

C 指针多 维数组 隐式转换

评论

0赞 Lundin 10/17/2023
指向数组的指针包含与数组本身相同的地址,以及数组中第一项的地址。为什么不呢?
0赞 pmg 10/17/2023
它们的值是相同的,它们的类型不是。 是指向数组(共 3 个整数)的指针; 是指向 int 的指针。想象一下,你用手指指着我......还有人用手指指着我的鼻子。你们俩都指向同一个“东西”吗?ptr+1*(ptr + 1)

答:

0赞 Vlad from Moscow 10/17/2023 #1

对于输出指针的初学者,您需要使用转换说明符而不是pX

printf("ptr=%p\n",( void * )( ptr+1) ); // ptr=0x60FEE4

printf("*(ptr)=%p\n", ( void * )*(ptr+1)); //*(ptr+1)=0x60FEE4

conversuib 说明符旨在输出 类型的对象。Xunsigned int

使用错误的转换说明符会调用未定义的行为。

由于指针的声明,表达式具有类型*( ptr + 1 )int[3]ptr

int (*ptr)[3]=arr_2D;

这相当于

int (*ptr)[3] = &arr_2D[0];

表达式中使用的数组指示符(极少数例外)将转换为指向其第一个元素的指针。

来自 C 标准 (6.3.2.1 左值、数组和函数指示符 )

3 除非它是 sizeof 运算符的操作数,或一元数 & 运算符,或者是用于初始化数组的字符串文字,一个 类型为“数组类型”的表达式将转换为表达式 使用类型“指向类型”,该类型指向 数组对象,并且不是左值。如果数组对象具有寄存器 存储类,则行为未定义。

因此,具有数组类型并用作参数表达式的表达式被隐式转换为指向其第一个元素的指针类型。*( ptr + 1 )int[3]int *

尽管表达式的类型和用作 printf 调用参数的类型是不同的(第一个具有类型,隐式转换后的第二个具有类型),但它们具有相等的值 - 数组的第二个“行”占用的内存范围的地址。ptr + 1*( ptr + 1 )int ( * )[3]int *arr_2D

因此,您具有以下具有数组类型的表达式的隐式转换链

int[3][3] (arr_2D)    -> int ( * )[3] (ptr)
int[3] (*( ptr + 1) ) -> int *

评论

0赞 Hossam Ahmed 10/17/2023
我不明白..(ptr+1) 输出一个位置,当使用 * 运算符时,它应该获取存储在其中的值,但它不会出现在代码中!
0赞 Vlad from Moscow 10/17/2023
@HossamAhmed 表达式 ptr + 1 指向类型为 int[3] 的数组arr_2D的第二行。因此,取消引用指针表达式 *( ptr + 1 ) ,您将获得 int[3] 类型的整个一维数组。
0赞 Vlad from Moscow 10/17/2023
@HossamAhmed 要获取数组 int 类型的第一个元素,您需要取消引用结果表达式,例如 **( ptr + 1 )。它类似于使用一维数组,例如 int a[] = { 1, 2, 3 };要获取数组的第一个元素,可以编写 printf( “%d\n”, *a );另一方面,在原始示例中,您有一个指向整个数组的指针。因此,第一次取消引用将只为您提供一维数组,如上面的示例所示。要获得它的第一个元素,您需要再取消引用它。
0赞 Hossam Ahmed 10/17/2023
多谢。。我现在明白了^^
1赞 0___________ 10/17/2023 #2

我将用更简单的话来解释:

  1. int (*ptr)[3]=arr_2D;定义为指向三个元素数组的指针。ptrint
  2. (ptr + 1)提供指向三个元素数组的指针int
  3. 取消引用指向数组的指针将给出一个由三个元素组成的数组*(ptr + 1)int
  4. 当在表达式(如函数参数)中使用时,它会衰减为指向其第一个元素的指针array
  5. 由于和衰减引用在内存中的相同位置,因此将打印相同的值。唯一的区别是指针的类型(ptr + 1)*(ptr + 1)printf

评论

0赞 Hossam Ahmed 10/17/2023
现在我明白了..谢谢^^