6

我开始阅读一些关于 C 中指针的文章,但我有一个我不明白的例子。

该示例来自此处:http ://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays

这里是:

让我们看一个稍微不同的问题。我们想要一个二维数组,但我们不需要所有的行都具有相同的长度。我们要做的是声明一个指针数组。下面的第二行将 A 声明为一个指针数组。每个指针都指向一个浮点数。这是一些适用的代码:

float  linearA[30];
 float *A[6];

 A[0] = linearA;              /*  5 - 0 = 5 elements in row  */
 A[1] = linearA + 5;          /* 11 - 5 = 6 elements in row  */
 A[2] = linearA + 11;         /* 15 - 11 = 4 elements in row */
 A[3] = linearA + 15;         /* 21 - 15 = 6 elements        */
 A[4] = linearA + 21;         /* 25 - 21 = 4 elements        */
 A[5] = linearA + 25;         /* 30 - 25 = 5 elements        */

 A[3][2] = 3.66;          /* assigns 3.66 to linearA[17];     */
 A[3][-3] = 1.44;         /* refers to linearA[12];           
                             negative indices are sometimes useful.
                             But avoid using them as much as possible. */

我的问题是为什么A[0]指针只指向五个元素而不是 ALL of linearA,因为数组的名称是指向其第一个成员的指针。

并且A[1] = linearA + 5;是连续 6 个元素 - 出于同样的原因?不A[1]应该是指向第 6 个成员的指针linearA吗?

有人可以解释我的错误在哪里吗?

4

5 回答 5

3

除了少数例外,在 C 中,数组名被转换为指向数组第一个元素的指针。是表达式linearA中的和的数组 30 :float

A[0] = linearA;

它被转换为指向float.

A是指向 的指针数组 6 float。的元素A是指向的类型指针floatA[0]指向数组的指针float而不是指向数组的指针也是如此。

A[i][j]在 C 中等价于*(A[i] + j)so A[i][j]is a float(取消引用指向float产生 a的指针float)。

于 2013-03-20T21:58:22.990 回答
1

A[0]是指向 的第一个元素的指针linearA。由于linearA是一个连续数组,因此该指针实际上允许linearA通过添加适当的偏移量来访问 30 个元素中的任何一个。但是,在这段代码中,您通过指向数组中的不同偏移量来模拟二维linearA数组。结果是类似 2D 的数组寻址:将您带到第 n 行A[n]的位置(即在 中的偏移量),并将您带到该行内的第 m 个元素。linearAA[n][m]

于 2013-03-20T22:03:17.373 回答
1

这是因为这一行设置了一个包含 6 个指针的数组float

float *A[6];

这一行将这些指针中的第一个设置为 30 的第一个元素

A[0] = linearA; 

因此 A 的每个元素都指向原始数组的一个子部分。但是,您必须分配它们-它们最初会指向随机地址。

第一个是初始地址(&linearA[0]),接下来的五个是以下地址。这些是可访问A[0][0]A[0][5]。因为数组对应指针的方式,你可以一直往上走,只要不超过30。

但是您可以分配A[n]给您喜欢的数组的任何部分。只要它是原始数组的一部分,它就会指向该成员,以及接下来的 5 个(或者你想要的任意多个)。

例如,通过指向A[1]&linearA[6]您将有效地设置一个二维数组(它类似于一个,但不像一个)。

于 2013-03-20T22:12:58.447 回答
1

我的问题是为什么 A[0] 是仅指向五个元素而不是所有线性 A 的指针,因为数组的名称是指向其第一个成员的指针。

您设置A[0]指向linearA哪个是数组中的第一个浮点数,A[0]是一个指针,因此不知道它指向的地址是什么。因此A[0],它不是指向仅五个元素的指针,它指向数组的开始位置,并且不知道数组的结束位置。

A[1] = 线性A + 5;是连续 6 个元素 - 出于同样的原因?A[1] 不应该是指向 linearA 的第 6 个成员的指针吗?

yesA[1]指向第六个元素,但如前所述,它是一个起始地址。

于 2013-03-20T22:18:17.643 回答
1

您发布的示例显示了一种称为Iliffe 向量的有点深奥的技术,这是在 C 中实现锯齿状数组的一种可能方法。锯齿状数组是一个矩阵,其中每一行都有不同的长度。

由于数组在 C 中是一维的,因此您正在创建一个linearA包含所有元素的单个数组,该数组被解释为一系列行,每行都有不同的大小。指针数组A包含指向每行第一个元素的指针,允许您使用行和列索引访问元素。

该代码显示了 C 指针和数组的几个有趣的特性:

linearA + 5

指针算术:将整数添加到指针(或数组)会给您一个指针,该指针指向原始指针之后的n 个元素。

A[3][2] = 3.66;

这种漂亮的语法使您可以将此结构视为二维矩阵。

此外,这可能是示例的要点,指针和数组是可互换的。这里,A[3]是一个指向浮点数的指针,因为A它被定义为一个指向浮点数的指针数组;appending[2]为我们提供了在原始指针指向的元素之后 2 个位置的元素。这类似于上面的指针算法,只是在这种情况下指针被取消引用。实际上,数组访问是根据指针定义的,因此X[5]等价于*(X+5).

A[3][-3]

这表明没有什么可以阻止您访问给定行之外的元素。在这种情况下,您正在访问元素 3所指向的位置之前A[3]的位置。这是很少需要的东西,它只在这种情况下有效,因为您将矩阵构建为具有连续元素。通常,访问数组分配范围之外的元素会使您的程序崩溃。

最后,回答你的问题:

并且A[1] = linearA + 5;是连续 6 个元素 - 出于同样的原因?不A[1]应该是指向第 6 个成员的指针linearA吗?

由于指针和数组是可互换的,A[1]既是指向 in 中第六个元素的指针,也是从inlinearA 第六个元素开始的数组linearA。语言中没有说后者有 6 个元素长,您必须在代码中实现该逻辑。

于 2013-03-20T23:06:26.033 回答