关于指针的一些干扰

时间:2018-08-24 13:17:58

标签: c pointers

我已经阅读了一些有关网站中的指针和Internet中的PDF的主题。但是到目前为止,有很多事情我还是不太清楚:

在PDF中写道,可以将具有10行20列的二维数组声明为$ rpm -q --whatprovides /etc/bashrc setup-2.11.4-1.fc28.noarch 而不是int (*ary)[20]

他们解释:

  

int array[10][20]被定义为指向一组连续的指针,   一维20个元素的整数数组。”

在互联网上的许多网站上,他们只是说ary是指向20个整数数组的指针的声明。

5 个答案:

答案 0 :(得分:3)

int array[10][20]是一个包含10个项目的数组,每个项目都是20个整数的数组。或者,如果您愿意:它是10x20 int的2D数组。

int (*ptr)[20]是指向20个整数的数组的数组指针。它不会为数组分配任何内存,但是可以指向一个。

如果你写

int array[10][20];
int (*ptr)[20] = array;

然后array“衰减”为指向第一个元素的指针。 int [10][20]的第一个元素是int[20]。并且int (*ptr)[20]是指向这样一个元素的指针,所以很好。

您可能会因为动态分配2D数组而感到困惑,可以这样做:

int (*ptr)[20] = malloc( sizeof(int[10][20]) );

在这里,ptr指向int[20]数组的第一个元素(int[10][20])。

答案 1 :(得分:2)

声明

int (*ary)[20];

int ary[10][20];

非常 不同。实际上,第一个确实声明了一个指向20个int元素数组的指针。第二个声明一个由20个int元素组成的10个数组的数组。


您要记住的是,数组自然会衰减到指向其第一个元素的指针。

对于像这样的简单数组

int simple_array[10];

然后在表达式中使用普通simple_array&simple_array[0]相同,表达式的类型为int *

现在是数组数组

int complex_array[10][20];

如果在表达式中使用complex_array,则它的 still 会导致指向其第一个元素的指针,即&complex_array[0]。现在的区别是表达式的 type &complex_array[0](或普通等效项complex_array)是int (*)[20]

使用此信息,您可以轻松创建指向complex_array的指针,并使它指向complex_array的第一个元素:

int (*complex_array_pointer)[20];

// Make complex_array_pointer point to the first element of complex_array
// i.e. make complex_array_pointer point to complex_array[0]
complex_array_pointer = complex_array;

答案 2 :(得分:1)

主要是要了解C除了一维数组之外没有其他任何东西。是的,C中并不真正存在2D数组(例如矩阵)。

但是,数组包含的元素都具有相同的字节大小(由sizeof给出)和类型。因此,您可以拥有数字数组,指针数组,struct -s数组,甚至还有数组数组(例如整数)。

因此,通过滥用,您可以说数组是一个矩阵(因此有人声称C中存在2D数组。我觉得这很夸张)。但是它(例如,声明为int a[10][20];之类的东西)实际上是一维数组(由20个整数组成)的一维数组(每个元素有10个元素)。在许多情况下,指针数组很有用(例如“字符串”数组)。

C99(或更高版本)中一个有趣的功能是flexible array member s。这样,您就可以巧妙地定义自己的Matrix abstract data type,用作opaque pointer(有关某些代码,请参见this答案)。

在许多情况下(特别是当您在赋值的右边将数组分配给某个左值(如变量),或将数组作为某个函数的参数传递给数组)时,数组会衰减为指针。但是它们的sizeof和类型不同。

浏览一些C reference网站(以及更晚的n1570 C标准,例如其§6.5.2.1 Array下标)。阅读How to debug small programs

BTW,在C中很少需要像int a[10][20];这样的C中所谓的2D数组(除非您专门研究在编译时已知的 fixed 尺寸矩阵上的数值计算;我想游戏开发人员可能经常使用类似typedef double transform3Dmatrix_ty[3][3];的类型)。在30多年的编程经验中,我几乎从未使用过2D阵列。

我不假装在几个段落中教你C。您会发现很多好书(和一些非常糟糕的书)。

答案 3 :(得分:1)

这些是数组:

int a[10];
int b[10][20];

这些是指针:

int *p1;
int (*p2)[20];

它们是不同的。他们不一样。

但是,即使它们不同,您也可以这样做:

p1 = a;
p2 = b;

现在p1指向ap2指向b

您说的p1 = a是简写。好像你写过

p1 = &a[0];

严格来说,p1指向a的第一个元素。同样,p2 = b类似于p2 = &b[0],并使p2指向b的第一个元素。但是,由于b是一个数组数组,所以b的第一个元素是20个整数数组。

此外,如果您将ab传递给函数,例如:

f(a, b);

该函数的定义应该是什么样?事实证明,有两种方法可以查看它。您可以声明

void f(int a[], int b[20][]) { ... }

这使f的参数看起来像您认为要传递的参数。但是事实证明实际上是传递了指针,因此f也可以这样声明:

void f(int *a, int (*b)[20]) { ... }

无论如何,这就是为什么您阅读的页面提示数组int a[10][20]与指针int (*p2)[20]之间存在某种等效性的原因。存在“某种等效”,但这并不意味着它们是同一类型。 (完全没有。因此,大多数人宁愿不再在这种情况下使用“对等”一词。)

答案 4 :(得分:-1)

您只需要考虑ary 是指向其第一个元素的指针。请注意,语法ary[index]*(ary + index)是等效的,它将帮助您了解其工作原理。