“Arrays = Pointers”*心灵狂热*。许多年后:“实际上,他们没有”*心灵再次被吹走*

时间:2013-06-08 05:14:30

标签: c arrays

上下文:

我在C中打开和关闭编程大约2年,之后发现a[i]只是*(a + i)的语法糖,因此相当于* (i + a)i[a]。我的现实被颠倒了,很多都是“AHA!”在接下来的几天学习和阅读(“那就是为什么数组总是通过引用传递!”等)之后的启示时刻。从那时起,我已经内化了指针/数组的等价并将其保持在我心中,所以想象一下,当我偶然发现这个名为“数组衰变”的东西时,这是多么可怕的震撼。这是典型的例子:

代码:

#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 个答案:

答案 0 :(得分:6)

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

有时还会提到另外一个上下文:使用字符串文字初始化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。)

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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

sizeof& operator是此规则的例外情况。

另外,我推荐书Expert C Programming,它使用整章解释指针和数组的差异和混淆。

答案 3 :(得分:-1)

将数组声明为局部变量或全局变量是指针与指针的不同之处。 int arr[100];分配400个字节的空间,而int *p仅分配4个。如果你为某个空格malloc,可以使用类似于数组的int *p局部变量,例如

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

当然,您还必须记得在以后释放该记忆。您还可以随意将声明为int arr[100]的局部变量传递给其形式参数类型为int *的函数。说到函数参数,数组和指针稍微等一点。

i[a]

不,如果我是一个int,这将无效。但其他三种形式是等价的。