首页 > 解决方案 > Difference between array of pointers and pointer to array?

问题描述

 char string1[3][4]={"koo","kid","kav"}; //This is a 2D array

 char  * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
 char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters

//I want to know differences between string1Ptr(pointer to array mentioned in question) and string(array of pointers mentioned in question). I only typed string1 here to give string1Ptr an address to strings

Besides the fact that string can point to strings of any size and string1Ptr can only point to strings of size 4 only(otherwise pointer arithmetic would go wrong), I don't see any differences between them.

For example,

   printf("%s\n", string1[2]);   // All print the same thing, ie, the word "kav"
   printf("%s\n", string1Ptr[2]);
   printf("%s\n", string[2]);

They all seem to perform the same pointer arithmetic.(My reason for assuming string and string1Ptr are almost similar besides for the difference I stated above)

So what are the differences between string and string1Ptr? Any reason to use one over the other?

PS: I'm a newbie so please go easy on me. Also, I did check C pointer to array/array of pointers disambiguation, it didn't seem to answer my question.

标签: cpointerspointer-to-pointer

解决方案


char string1[3][4]={"koo","kid","kav"}; //This is a 2D array

char  * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters

除了string可以指向任何大小的字符串并且 string1Ptr只能指向大小为 4 的字符串这一事实(否则指针运算会出错)之外,我在它们之间没有任何区别。

它们是绝对的、根本的不同,但是 C 会费力地向你隐藏区别。

string是一个数组。它标识一个连续的内存块,其中存储了它的元素。在这个例子中,这些元素恰好是类型char *,但这是一个相对次要的细节。可以将这里类比为包含多个房间的房子——这些房间在物理上是房子的一部分,并且存在于房子的物理边界内。我可以随心所欲地装饰房间,但它们始终是那所房子的房间。

string1Ptr是一个指针。它标识了一块内存,其内容描述了如何访问另一个不同的内存块,其中有一个 4 chars 的数组。在我们的房地产类比中,这就像一张纸,上面写着“42 C 街,主卧室”。使用该信息,您可以找到房间并根据需要重新装修,就像在其他情况下一样。但是您也可以用定位器替换纸张,用于不同的房间,可能在不同的房子里,或者随机文本,或者您甚至可以烧掉整个信封,而不会影响 C 街的房间。

string1,就其本身而言,是一个数组数组。它标识存储其元素的连续内存块。这些元素中的每一个本身都是一个 4 chars 的数组,顺便说一下,它恰好是string1Ptr可以指向的对象的类型。

例如,

printf("%s\n", string1[2]);   // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);

string它们似乎都执行相同的指针运算。(我假设的原因string1Ptr除了我上面提到的差异之外几乎相似)

...这就是 C 隐藏区别的地方。了解 C 数组的基本内容之一是,在几乎所有表达式中,*数组类型的值都会默默地自动转换为指针 [指向数组的第一个元素] . 这有时被称为指针“衰减”。因此,索引运算符是指针上的运算符,而不是数组上的运算符,实际上它在您的三个示例中确实具有类似的行为。实际上,string1衰变指向的指针类型与 的类型相同string1Ptr,这就是允许为后者提供的初始化的原因。

但是你应该明白,在这三种情况下,操作的逻辑顺序是不一样的。首先,考虑

printf("%s\n", string1Ptr[2]);

这里,string1Ptr是一个指针,索引运算符可直接应用于该指针。结果等价于*(string1Ptr + 2),其类型为char[4]。作为数组类型的值,它被转换为指向第一个元素的指针(导致 a char *)。

现在考虑

printf("%s\n", string1[2]);

string1是一个数组,因此首先将其转换为指向其第一个元素的指针,从而产生一个 type 的值char(*)[4]。这与 的类型相同string1Ptr1,并且评估会相应地进行,如上所述。

但这个有点不同:

printf("%s\n", string[2]);

这里,string是一个指针,因此索引操作直接应用于它。结果等价于*(string + 2),其类型为char *。不执行自动转换。

有任何理由使用其中一个吗?

许多,双向的,取决于您当时的特殊需求。一般来说,指针更灵活,尤其是在处理动态分配的内存时需要它们。但他们遭受的问题是

  • 指针可能在范围内,但不指向任何东西,并且
  • 声明一个指针不会为它创建任何指向的东西。还,
  • 即使一个指针在程序执行期间一次指向某个东西,并且它的值随后没有被程序写入,它仍然可以停止指向任何东西。(这通常是指针比它指向的对象寿命长的结果。)

此外,它既可以是优势,也可以是劣势

  • 一个指针可以在其生命周期内任意次数地自由分配指向一个新对象。

一般来说,数组更容易用于多种用途:

  • 声明一个数组会为其所有元素分配空间。您可以选择在声明时为它们指定初始值,或者在某些(但不是全部)情况下使用默认初始化。
  • 数组的标识符是有效的,并且在其范围内的任何位置都引用该数组。
  • 可选地,如果提供了初始化程序,则数组声明可以使用它来自动确定数组维度。

*但只有几乎所有。有一些例外,最重要的是运算符的操作数sizeof


推荐阅读