C语言中的数组指针

5
你如何解释以下代码行?

你如何解释以下代码行?

int (*arrayABC)[10];

在我的教材中,它说我们有一个指向整数数组第0个元素的指针的指针。
然而,我不太理解这个概念。
我的理解是:我们有一些变量,它的值是某个地址。这个地址就是未命名整数数组的第0个元素的地址。基本上,我们有一个指向第0个元素的指针。
那么为什么还需要一个指向指针的指针呢?

诚然,这并不足以回答你的问题,但当你在处理C声明时,Cdecl总是一个很好的起点。无论如何,那是什么教科书? - Fabio says Reinstate Monica
请注意,有时拥有指向指针的指针是很好和有用的。然而,正如答案所解释的那样,这并不是你在示例中拥有的。 - John Bollinger
@FabioTurati 链接可以进行定制。例如arrayABC作为指向包含10个整数的数组的指针 - chux - Reinstate Monica
1
你能否留下一张关于你正在阅读的书籍的便条,并发布确切的引用语?这样我们就可以将该书列入黑名单,并在互联网上公开谴责作者。 - Lundin
3个回答

14

这是指向数组的指针。它不是指向指针的指针。数组和指针是不同的。一个数组有一个地址,但一个数组本身并不是一个地址。一个数组是一系列连续的元素。

该指针指向整个数组,而不仅仅是第一个元素,就像 float * 指向整个浮点数而不仅仅是第一个字节一样。

如果您有如下内容:

int foo[10];
int (*arrayABC)[10] = &foo;

那么表达式(*arrayABC)foo是相同的。例如,foo[3](*arrayABC)[3]相同。


所以基本上这个表达式与 int arrayABC[10] 相同,唯一的区别是我们可以像 arrayABC++ 这样做些事情? - Kevin Wu
@KevinWu 不,它并不像那样。int x[10];int (*x)[10];之间的区别就像float y;float *y;之间的区别一样。 - M.M
如果我对指针进行取消引用操作(*arrayABC),会发生什么? - Kevin Wu
@KevinWu 在我的答案中添加了这个。你可以像使用指向的数组的名称一样,以完全相同的方式和行为使用 (*arrayABC) - M.M
1
@raymai97 是的,写成 int b[10]; memcpy(b, *arrayABC, sizeof b);。在C语言中,赋值运算符不能用于数组,你必须使用memcpy或循环逐个赋值元素。 - M.M
显示剩余7条评论

3
如果您拥有类型为T的对象,则可以声明指向该对象的指针,如下所示:
T obj;

T *ptr = &obj;

现在让我们假设类型T已以下列方式定义:
typedef int T[10];

因此,上述代码

T obj;

T *ptr = &obj;

可以使用typedef定义来重写:

int obj[10];

int (*ptr)[10] = &obj;

在这两种情况下,当 T 是某个抽象类型或者 Tint[10] 的别名时,ptr 都是一个指向对象的指针。在最后一种情况下,ptr 是指向类型为 int10 个元素数组的指针。也就是说,ptr 指向的对象具有数组类型。数组和指针是不同的类型。
尝试以下简单的演示程序。
#include <stdio.h>

int main( void )
{
    typedef int T[10];

    T a;

    T *pa = &a;

    printf( "%zu\n", sizeof( *pa ) );

    int b[10];

    int ( *pb )[10] = &b;

    printf( "%zu\n", sizeof( *pb ) );
}    

它的输出是

40
40

如您所见,这两个值都等于一个由10个元素组成的整数数组的大小。因此,指针指向数组。

如果您写下:

int *arrayABC[10];

您将得到一个长度为10的指向 int * 类型的指针数组。

如果您编写:

int (*arrayABC)[10];

您将获得一个指向由10个整数构成的数组的指针。


1
在我的教科书中,它说我们有一个指向整数数组第0个元素的指针的指针。
你的教科书表述不太好,我们就这样吧。它是指向一个包含10个int元素的数组的指针。
我可以有点理解书的意思。鉴于声明:
int (*a)[10];

expression *a 的类型将为 int [10](10个int元素的数组)。然而,除非该表达式是sizeof或一元&运算符的操作数,否则它将从类型int [10]转换(“衰减”)为int *,并且该表达式的值将是数组第一个元素的地址:

Expression       Type        "Decays" to        Value
----------       ----        -----------        -----
        *a       int [10]    int *              Address of first element of the array;
                                                equivalent to `&(*a)[0]`.  

因此,如果我调用一个函数,例如:
foo( *a );

这个函数实际接收的是指向指针所指数组第一个元素的指针(它的类型将是int *而不是int **)。

因此,实际上,a经常表现为指向数组第一个元素的指针的指针;然而,它的类型不是“指向int的指针的指针”,类型很重要。例如:

int (*a)[10];
int **b;

那么,接下来的操作将会有不同的行为:
sizeof *a vs. sizeof *b
a + i vs b + i (also applies to a++ vs b++)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接