int main(){
int a[][3]={1,2,3,4,5,6};
int (*ptr)[3]=a;
printf(" %d",(*ptr)[1]) ;
}
我知道变量
ptr
是类型int
的第一个1d数组的指针,换句话说变量ptr
将存储前3个整数的地址,首先让我们假设基地址a
是 1000
所以我认为这个二维数组将以这种形式存储在内存中:
elements: | 1 | 2 | 3 || 4 | 5 | 6 |
addressed of each element: | 1000 | 1004 | 1008 || 1012 | 1016 | 1020 |
---------------------------------||---------------------------------
addressed of each array: 1000 1012
所以
ptr
将存储值 1000
,这是第一个数组的地址。这意味着 *ptr
或 (*ptr)[0]
会给我第一个元素的地址,而 *ptr+1
或 ((*ptr)[1])
会给我第二个元素的地址,依此类推。
据我所知
*ptr[1]
会给出第二个元素的地址,而不是它的值。
但是从输出看来我错了。所以我想知道我的过程中有什么问题。
这部分之前你是对的:
这意味着
或*ptr
会给我第一个元素的地址(*ptr)[0]
*ptr
会那样做。 (*ptr)[0]
将取消引用数组指针,然后取消引用结果数组,为您提供第一项的值,1
.
类似地,
(*ptr)[1])
将首先给你一个数组,然后是该数组中的第二个项目,2
.
据我所知,*ptr[1] 将给出第二个元素的地址,而不是它的值。
不,因为
[]
的优先级高于 *
,所以 ptr[1]
将首先给你第二个数组的(地址)。然后你取消引用它,你会得到第二个数组中第一项的值,4
.
这里的关键是一旦你取消引用一个指向数组的指针,你最终会得到一个数组 - 就像任何数组在“数组衰减”等方面的行为一样
最佳实践:
*
取消引用数组指针。 ptr[0][0]
不那么模糊了。这种语法是在这种情况下使用数组指针的全部要点。int a[][3]={1,2,3,4,5,6};
。 C 允许它,但它是糟糕的风格并且使诊断的某些可能性静音。相反,这应该是int a[][3]={ {1,2,3}, {4,5,6} };
作为奖励也是可读的,自我记录的代码。让我们考虑一下调用中使用的表达式
printf
printf(" %d",(*ptr)[1]) ;
对于初学者来说,指针
ptr
指向二维数组int[3]
类型的第一个元素。
int (*ptr)[3]=a;
这是由于初始化列表
int a[][3]={1,2,3,4,5,6};
二维数组有两个
int[3]
.类型的元素
所以取消引用指针
*ptr
你得到一个int[3]
类型的左值,它是一个一维数组。然后对该数组应用下标运算符( *ptr )[1]
,它产生一维数组的第二个元素。
所以值
2
将被输出。
这意味着 *ptr 或 (*ptr)[0] 会给我第一个地址 元素
表达式
*ptr
和( *ptr )[0]
是两个不同类型的实体。The expression
*ptryields lvalue of the type
int[3]`,使用din表达式它又可以隐式转换为指向第一个元素的指针获得的数组。
表达式
( *ptr )[0]
产生所获得的int
类型数组的第一个标量元素。
据我所知,*ptr[1] 将给出第二个地址 元素,而不是它的价值。
表达式
ptr[1]
产生二维数组int[3]
类型的第二个元素在这个表达式*ptr[1]
中获得的类型int[3]
的对象被隐式转换为类型int *
的指针并取消引用指针产生二维数组第二个元素int
类型的第一个元素。
为了更清楚地考虑如何评估下标运算符。
例如,表达式
ptr[0]
等同于 *( ptr + 0 )
又等同于 *ptr
.
表达式
(*ptr)[1]
等同于ptr[0][1]
.
表达式
*ptr[1]
等同于 *(ptr[1] )
又等同于 ptr[1][0]
.
一般来说,
ptr[i][j]
可以用多种方式重写。例如
( *( ptr + i ) )[j]
*( *( ptr + i ) + j )
*( ptr[i] + j )