2

语境:

在发现这a[i]只是语法糖,*(a + i)因此相当于 *(i + a)i[a]. 我的现实被颠倒了,许多“啊哈!” 在接下来的几天的学习和阅读中,启示性的时刻紧随其后(“这就是为什么数组总是通过引用传递!”等)。从那时起,我将指针/数组等价性内化并将其牢记在心,所以想象一下,当我偶然发现这个叫做“数组衰减”的东西时是多么粗鲁的震惊。这是典型的例子:

代码:

#include <stdio.h>

int Length(int*);

int main () {
  int arr[100];
  printf("Length of array: %d\n",(int)(sizeof(arr)/sizeof(arr[0])));
  printf("Length of array: %d\n",Length(arr));
  return 0;
}

int Length(int arr[]) {
   return sizeof(arr)/sizeof(arr[0]);
}

结果:

Length of array: 100
Length of array: 2

问题:

所以事实证明,C毕竟对数组有一定的认识!在声明数组的 main 中,程序能够正确报告它的大小。现在我想知道有多少数组语法只是指针操作的语法糖(以前我假设:全部)。C实际上确实有数组,它们的局限性是什么?这个例子表明,只要你在同一个函数中,就有可能得到它们的长度,你还能做什么很酷的事情?在这个腐烂的东西开始之前,你能走多远?

4

4 回答 4

6

“旧” C 语言中有两个运算符不会触发数组类型衰减:sizeof运算符和一元运算&符。sizeof计算整个数组的大小(而不是指针大小),同时&返回指向数组类型的指针(不是指针类型)。C99 补充说_Alignof,正如 Eric 在评论中指出的那样。

有时还会提到另一种上下文:使用字符串文字初始化 char 数组(即字符串文字不会衰减为指针)。

也可以这样说:在对象上下文(AKA 左值上下文)中,数组保留它们的“数组性”,而在值上下文(AKA 右值上下文)中,它们立即衰减为指针。

PS作为一个历史注释:C 语言的祖先之一——B 语言——确实将数组实现为物理指针,这意味着 B 中的每个数组实际上都是一个指向独立分配的内存块的指针。最初假设此实现也将延续到 C。但是,C 必须有struct类型。B 风格的数组因为将数组作为struct对象的成员而产生了不必要的复杂性。他们会使对象的初始化变得不struct平凡,struct对象将变得不可复制memcpy等等。这在 C 中被认为是不可接受的。因此,数组被重新设计为当前的形式。C 数组不是指针,但它们仍然从 B 语言中模仿祖父母的类似指针的行为,这常常使学习 C 的人感到困惑。

(有关完整故事,请参见此处http://cm.bell-labs.com/cm/cs/who/dmr/chist.html。)

于 2013-06-08T05:21:34.547 回答
3

数组的大小在传递给函数时会“丢失”。正如您所指出的sizeof,作为编译时的东西,它会看到“真实”大小。这可以工作,因为sizeof它根本不是一个函数,正如您可以通过不带括号使用它来证明的那样(例如sizeof arr,虽然奇怪sizeof some_type的是不合法的 C)。

于 2013-06-08T05:19:23.370 回答
2

说数组和指针是“等价的”意味着它们既不是相同的,也不是可以互换的。它的意思是指针算术和数组索引在C中是等价的,指针和数组是不同的。

对出现在表达式中的 array-of-T 类型对象的引用衰减为指向其第一个元素的指针;结果指针的类型是指向 T 的指针。也就是说,只要数组出现在表达式中,编译器就会隐式生成指向数组第一个元素的指针,就好像程序员已经编写了&a[0].

sizeof或者& operator是这个规则的例外。

另外,我推荐《Expert C Programming 》一书,它用一整章来解释指针和数组的区别和困惑。

于 2013-06-08T05:27:34.050 回答
-1

将数组声明为局部变量或全局变量是它与指针不同的地方。int arr[100];分配 400 个字节的空间,而int *p只分配 4 个。如果为它分配一些空间,则可以使用int *p类似于数组的局部变量,例如

int *p = (int *)malloc(100 * sizeof(int));

当然,您还必须记住稍后释放该内存。您还可以随意将声明为int arr[100]形式参数具有 type 的函数的局部变量传递int *。当涉及到函数参数时,数组和指针更加等价。

i[a]

不,如果 i 是 int,那将不起作用。但其他三种形式是等价的。

于 2013-06-08T05:24:55.393 回答