我想加深对C语言中指针相关语法的理解,我注意到,如果我先创建一个int的数组。int(*)[]
是给这个数组一个指针的方法,似乎也可以通过简单的使用 int *
. 所以我很困惑,下面代码中指针b和指针c有什么区别?如果它们是不同的,那么我应该在什么时候使用一种方式而不是选择另一种方式?
#include <stdio.h>
int main(void)
{
int a[3];
int* b = a;
int (*c)[3] = &a;
printf("%p\n", a);
printf("%p\n", b);
printf("%p\n", c); //these 3 outputs are same.
}
我只是试着加了几行代码来进一步理解这个问题。
a[2] = 3;
printf("%i\n", a[2]); // = 3
printf("%i\n", b[2]); // = 3
看起来b和c是不同的,因为 printf("%i\n", c[2]) 会产生一个错误。如何解释和理解以上这些?
既是 b
和 c
指向同一个内存,但差别很大。
int
和指向3个数组的指针 int
s)b
解引到一个由 b
而 c
被派生为3个数组。int
s,这意味着你可以给一个整数。*b
(*b = 10;
),但你却不能用同样的方式来处理 c
(但只限于指定的索引 (*c)[0] = 10
)b + 1
将增加价值的 b
由 sizeof(int)
而 c + 1
将增加价值的 c
由 3*sizeof(int)
如果它们是不同的,我什么时候应该使用一种方式而不是选择另一种?
和C语言中的其他类型一样,应该根据你的需求和应用来使用。最常用的是 int *b;
选项,因为它给了你更多的灵活性。有了这样的指针,你可以处理任何大小的数组,它更常用,也更易读。而指向数组的指针可以将你绑定到一个预先定义好的大小的数组上,它的语法可读性较差(在我看来),因此将更难审查和调试代码。在我的经验中,我从来没有见过使用指针到数组的生产代码,但这并不意味着你不能使用它,如果你发现它在你的应用程序中的任何优势。
所以我很困惑,下面代码中的指针b和指针c有什么区别?
它们的类型。b
的类型是 int *
和 c
属于 int (*)[3]
.
数组的地址和数组中第一个元素的地址是一样的,所以它们指向的内存位置在这里会是一样的,但是按照它们的类型,对它们进行操作,比如指针运算,会产生完全不同的结果。
我们先来直观的表示一下。
int [3] int * int (*)[3]
------- ----- ----------
+---+
| | a[0] b[0] c[0]
+ - +
| | a[1] b[1]
+ - +
| 3 | a[2] b[2]
+---+
| | c[1]
+ - +
| |
+ - +
| |
+---+
| | c[2]
+ - +
| |
+ - +
| |
+---+
最左边的是内存的视图,它是一个3元素数组的序列。int
其余各栏显示了每一栏的情况。a[i]
, b[i]
和 c[i]
的解释。
由于 a
被宣布为 int [3]
和 b
被宣布为 int *
,每个 a[i]
和 b[i]
有型 int
(a[i] == *(a + i)
).
但是 c
是不同的--因为 c
被声明为"指针 到3元素阵列 int
" (int (*)[3]
),那么每个 c[i]
有类型"三元素阵列 int
" (int [3]
). 所以,与其说是第三要素的 a
, c[2]
是 第一 的元素 第三次 下面的3元素阵列 a
.