炫酷网站设计免费自学网

那这样p和*p记录的地址不一样了吗?
不,p 和 *p 记录的地址在某种意义上是“相同”的,但它们在类型和使用方式上有所不同。
-
p的地址:p是一个指针,它本身存储了一个地址,这个地址是二维数组arr的第一行(或称为第一个一维数组)的首元素的地址。因此,p的值(即它存储的地址)是指向arr[0][0]的。 -
*p的“地址”:当我们说*p的地址时,实际上有些误导,因为*p不是一个指针,而是一个数组(尽管在表达式中它会被退化为指向其首元素的指针)。但是,如果我们谈论*p“指向”的地址,我们实际上是在谈论*p(即arr[0])的首元素的地址,这与p存储的地址是相同的,都是&arr[0][0]。
然而,重要的是要理解 p 和 *p 在类型和使用上的差异:
-
类型:
p的类型是int (*)[5],即一个指向包含5个整数的数组的指针。而*p的类型是int[5],即一个包含5个整数的数组(但在表达式中它会被退化为int*)。 -
使用:你不能直接对
*p进行赋值或将其作为函数参数传递(因为它不是一个左值),但你可以通过索引来访问它的元素(如(*p)[0])。而p可以被赋值,可以作为函数参数传递,也可以进行指针算术运算(如p + 1将指向下一行)。
为了澄清,让我们再次强调:p 存储了一个地址,这个地址是二维数组第一行的首元素的地址。而 *p 在表达式中会被退化为指向这个首元素的指针,但技术上 *p 表示的是整个一维数组的“视图”。然而,我们总是通过索引来访问这个数组中的元素。
总结:p 和 *p 在“指向”的地址上是相同的(都指向 arr[0][0]),但它们的类型和使用方式完全不同。
那*p+1会得到什么?
在C语言中,当 *p 表示一个数组(尽管在表达式中它通常会被退化为指向其首元素的指针)时,直接对 *p 进行算术运算(如 +1)是不合法的,因为 *p 本身不是一个可修改的左值,也不是一个指针。
然而,如果你写了 *p + 1,这里实际上发生的是指针算术的“假象”。由于 *p 在表达式中会被退化为指向数组首元素的指针(即 int* 类型),*p + 1 的结果是一个指向 arr[0][1] 的指针(即 &arr[0][1])。这里,+1 是按照指针的步长(即指向类型的大小)来计算的,对于 int* 类型的指针来说,步长通常是 sizeof(int)。
但是,重要的是要明白这种写法(*p + 1)虽然在技术上是合法的,并且可能符合你的预期(得到指向下一个元素的指针),但它实际上是在对已经退化为指针的 *p 进行操作,而不是直接对数组本身进行操作。
如果你想要访问二维数组中的下一个元素(比如从 arr[0][0] 移动到 arr[0][1]),你应该使用 (*p)[1]。但是,如果你想要得到指向下一个元素的指针,那么 *p + 1 是正确的写法,尽管它看起来可能有些令人困惑。
然而,如果你想要遍历二维数组的行,你应该使用指针 p 本身进行算术运算,比如 p + 1 会指向二维数组的下一行(即 &arr[1])。
总结一下:
*p + 1得到的是指向arr[0][1]的指针。(*p)[1]访问的是arr[0][1]的值。p + 1指向二维数组的下一行。
