我可以声明:
int (*ap)[N];
所以ap
是指向大小为N的int数组的指针。为什么这个有用?如果我将它传递给函数,它可以用它做什么有用的东西它只能用一个指向数组内容的普通指针呢?
C常见问题解答说:
2.12:如何声明指向数组的指针?
通常,你不想。
答案 0 :(得分:13)
指向数组的指针可用于动态分配多维数组N,其中N-1维已知。下面创建一个Nx3数组。
int (*ap)[3];
ap = malloc(N * sizeof(*ap));
/* can now access ap[0][0] - ap[N-1][2] */
@Adam E / Cruachan,这与指针指针不同。 ap是指向包含三个连续整数的内存块的单个指针。 ap ++将指针地址前进到下一个三个整数的块。对于int **pp;
,pp指向一个整数指针,每个指针都可以指向内存中任何位置的整数。
+-----+ +------+ +-----+
ap ---> | int | vs. pp ---> | int* | -> | int |
| int | +------+ +-----+
| int | pp+1 -> | int* | -\
+-----+ +------+ \ +-----+
ap+1 -> | int | : : -> | int |
| int | +-----+
| int |
+-----+
: :
答案 1 :(得分:6)
如果递增指针,它将指向下一组N个元素的开始。
这不是什么大问题,它的使用取决于开发人员。
答案 2 :(得分:2)
真的没用。但有时使用指向数组的指针,例如在Microsoft Windows API中 - 我在那里看到了很多这样的东西。
答案 3 :(得分:2)
在某些情况下,您希望跨程序传递内存位置。例如,一个Windows API可能希望你传递一个指向数据结构或数组的指针,就像你用其他语言编程一样,比如c#。 Windows API并不关心目标语言如何处理数组,对于Windows API,它只是内存中的一个字节流,它将填充它,并将其发送给您。为了避免交叉语言类型不匹配在某些情况下我们使用指向数组的指针而不是隐式数组名称作为指针。除此之外不能保证隐式数组名称是长指针,一些编译器可能会将其优化为带有段的相对值。指向数组的指针保证它是机器寄存器大小的顺序,您可以指向可用RAM中任何位置的位置。
答案 4 :(得分:2)
通常,您唯一一次看到指向数组的指针(T (*a)[N]
)是一个函数参数,其中a
是一个二维数组:
void foo(int (*a)[N], size_t count)
{
size_t i;
for (i = 0; i < count; i++)
a[i][j] = ...;
...
}
void bar(void)
{
int arr[M][N];
foo(arr, M);
}
请注意,对于函数参数声明,int a[][N]
等同于int (*a)[N]
,但对于函数参数声明,这只是 true:
void foo (int a[][N], size_t count) {...}
指向数组的指针通常不如指向基类型的指针有用,因为您需要知道数组大小才能正确声明指向它的指针(指向int的10元素数组的指针与指向一个20元素的int数组。就个人而言,我在20多年的编程中没有找到太多用处。
请记住,在大多数情况下,数组表达式(例如上面的arr
)将其类型隐式地从“N元素数组T”转换为“指向T”(除非数组表达式为sizeof
或&
的操作数,或者数组是在声明中用作初始值设定项的字符串文字。在这种情况下,对foo的调用中arr
的类型被隐式地从“N元素数组的M元素数组”转换为“指向N元素数组int的指针”。
鉴于声明T a[M][N]
,以下所有表达式将计算到相同的位置(数组中第一个元素的地址),但类型将不同,如下所示:
Expression Type Implicitly converted to ---------- ---- ----------------------- a T [M][N] T (*)[N] a[0] T [N] T * &a T (*)[M][N] &a[0] T (*)[N] &a[0][0] T *
答案 5 :(得分:0)
这可能会影响主观/议论,但......
在我看来,指向数组的指针都在语言中,因为它们属于语言。每个其他可声明的数据类型都有指针,所以这些也在这里。我从来没有见过任何人从中获得真正有用的工作。假设它们允许一个需要数组的原型而不是指向该元素的指针,但是......
答案 6 :(得分:-1)
对我来说,做一个指向数组的指针似乎没用。在C中,数组已经是指向该数据类型块的指针。
int (*ap)[N];
int **ipp;
都是相同的数据类型(指向Integer的指针)。唯一的区别是有分配给ap的N个整数的空间。
没有必要通过指向函数的指针传递数组,例如,为了更改该函数中数组的内容,因为它已经是指针。作为一般规则,我认为这是不必要的,只是需要取消引用指针以获取数组中的数据。但是,我确信在某个地方有一个程序或算法可以找到它的合法用途。
答案 7 :(得分:-1)
以下代码是我文章的一部分: C C ++中的指针和数组
您可以查看@ http://pointersandarrays.blogspot.com/
指针和2D数组
以下代码段说明了如何声明和访问2D数组。 2D Array下面是一个单维数组。在使用以下代码后,您将确保这一点。
代码段#4
#include<iostream&rt;
using namespace std;
int main()
{
cout<< "Understanding Pointers and 2 D Arrays"<<endl;
cout<< "----------------------\n"<<endl;
//Declaration of a 2D Array.
int tab[3][5];
//Total space required : 3*5 * sizeof(int) = 15 * sizeof(int)
//Funda : Since the amount of required space is known by compiler, contiguous 15 memory cells are allocated here.
//Hence the case is similar to a 1 D Array of size 15. Lets try this out!
//Array initialization using array name
for(int i=0; i<3;i++)
for(int j=0; j<5;j++)
tab[i][j]=i+2*j;
//Print array using array name
cout << "\nPrint array using array name ..."<<endl;
for(int i=0; i<3;i++)
{
for(int j=0; j<5;j++)
printf("%2d ",tab[i][j] );
printf("\n");
}
//Print array using a pointer. Proof of 1 D array being allocated
cout << "\nPrint array using a pointer. Proof of 1 D array being allocated ..." << endl;
int *tptr;
tptr = &tab[0][0]; // pointer tptr points at first element of the array.
for(int i=0; i<15;i++)
printf("%d ",*(tptr+i) );
tptr = &tab[0][0];
cout << "\nNotice that array is printed row by row in a linear fashion."<<endl;
return 0;
}
输出#4:
Understanding Pointers and 2D Arrays
Print array using array name ...
0 2 4 6 8
1 3 5 7 9
2 4 6 8 10
Print array using a pointer. Proof of 1 D array being allocated ...
0 2 4 6 8 1 3 5 7 9 2 4 6 8 10
Notice that array is printed row by row in a linear fashion.
Understanding Pointers and 2D Arrays
Print array using array name ...
0 2 4 6 8
1 3 5 7 9
2 4 6 8 10
Print array using a pointer. Proof of 1 D array being allocated ...
0 2 4 6 8 1 3 5 7 9 2 4 6 8 10
Notice that array is printed row by row in a linear fashion.
答案 8 :(得分:-3)
我认为整个讨论的结论是从不。这里没有人真正证明了这种结构的用途,其他东西不会以更易于理解的方式起作用。