为什么用C衰变数组指针? [英] Why do arrays in C decay to pointers?

查看:150
本文介绍了为什么用C衰变数组指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[这是其他地方最近的讨论启发的问题,我会正确提供一个答案吧。]

[This is a question inspired by a recent discussion elsewhere, and I'll provide an answer right with it.]

我想知道数组的奇怪现象Ç腐朽为指针,例如作为函数参数使用时。这似乎只是如此不安全。这也是不方便用它明确地传递长度。我的可以的传递其他类型的骨料 - 结构 - 完美深受值;结构不衰。

I was wondering about the odd C phenomenon of arrays "decaying" to pointers, e.g. when used as function arguments. That just seems so unsafe. It is also inconvenient to pass the length explicitly with it. And I can pass the other type of aggregate -- structs -- perfectly well by value; structs do not decay.

这是什么设计决定背后的原因是什么?它是如何与语言集成?为什么那里结构区别吗?

What is the rationale behind this design decision? How does it integrate with the language? Why is there a difference to structs?

推荐答案

依据

让我们来看看函数调用,因为问题是很好的可见的有:为什么不只是传递给函数作为数组的数组,按值,作为副本

Let's examine function calls because the problems are nicely visible there: Why are arrays not simply passed to functions as arrays, by value, as a copy?

有首先是一个纯粹务实的原因:阵列可大了;它可能不是最好按值传递他们,因为他们
可能超过堆栈大小,特别是在20世纪70年代。第一个编译器是写在PDP-7与9 KB RAM。

There is first a purely pragmatic reason: Arrays can be big; it may not be advisable to pass them by value because they could exceed the stack size, especially in the 1970s. The first compilers were written on a PDP-7 with about 9 kB RAM.

还有植根于语言更多的技术原因。这将是很难产生code与参数的大小在编译的时候是不知道一个函数调用。对于所有的阵列,包括现代的C变长数组,只需将地址放在调用堆栈上。一个的地址的是当然众所周知的大小。即使语言携带的运行时间大小信息不正确在栈上传递的对象精心制作的数组类型。这些语言通常通过手柄绕,这是C已经有效地完成,也为40年。参看这里乔恩斯基特和一本图文并茂的解释,他引用(原文如此)的这里

There is also a more technical reason rooted in the language. It would be hard to generate code for a function call with arguments whose size is not known at compile time. For all arrays, including variable length arrays in modern C, simply the addresses are put on the call stack. The size of an address is of course well known. Even languages with elaborate array types carrying run time size information do not pass the objects proper on the stack. These languages typically pass "handles" around, which is what C has effectively done, too, for 40 years. Cf. Jon Skeet here and an illustrated explanation he references (sic) here.

现在的语言可以使它一个数组总是有一个完整的类型的要求;即,每当它被使用,其完整的声明包括大小必须是可见的。这一点,毕竟从结构需要什么C(它们被访问时)。因此,结构可以按值传递给函数。要求对阵列完整的类型以及会使函数调用容易编译并避免需要额外的传递长度参数:的sizeof()仍然会按预期被叫方内。但是想象一下这是什么意思。如果大小是数组的参数类型的真正的一部分,我们需要一个独特的功能,每个数组大小:

Now a language could make it a requirement that an array always have a complete type; i.e. whenever it is used, its complete declaration including the size must be visible. This is, after all, what C requires from structures (when they are accessed). Consequently, structures can be passed to functions by value. Requiring the complete type for arrays as well would make function calls easily compilable and obviate the need to pass additional length arguments: sizeof() would still work as expected inside the callee. But imagine what that means. If the size were really part of the array's argument type, we would need a distinct function for each array size:

// for user input.
int average_Ten(int arr[10]);

// for my new Hasselblad.
int average_ThreeTrillionThreehundredninetythreeBillionNinehundredtwentyeightMillionEighthundredsixthousandfourhundred(int arr[16544*12400]);
// ...

在事实上,它是完全媲美传递结构,这类型不同,如果它们的元素不同(比如,一是结构与10 INT元件和一个与16544 * 12400)。很明显,阵列需要更多的灵活性。例如,如展示一个人不能合理提供通常可用的库函数内搭数组参数

In fact it would be totally comparable to passing structures, which differ in type if their elements differ (say, one struct with 10 int elements and one with 16544*12400). It is obvious that arrays need more flexibility. For example, as demonstrated one could not sensibly provide generally usable library functions which take array arguments.

这强类型的难题,事实上,在C ++中,当一个函数具有一个数组的引用会发生什么;这也是为什么没有人做,至少没有明确的原因。这是完全不方便的是,除了适用于针对特定用途的情况下无用的地步,而在一般的code:C ++模板提供编译时的灵活性这是不是在C语言

This "strong typing conundrum" is, in fact, what happens in C++ when a function takes a reference to an array; that is also the reason why nobody does it, at least not explicitly. It is totally inconvenient to the point of being useless except for cases which target specific uses, and in generic code: C++ templates provide compile-time flexibility which is not available in C.

如果在现有的C,被誉为大小的数组确实应该按值传递总有将它们包装在一个结构的可能性。我记得在Solaris上一些与知识产权相关的头文件中定义地址的家庭结构在他们的阵列,允许各地复制它们。由于结构的字节布局是固定的,众所周知,这是有道理的。

If, in existing C, indeed arrays of known sizes should be passed by value there is always the possibility to wrap them in a struct. I remember that some IP related headers on Solaris defined address family structures with arrays in them, allowing to copy them around. Because the byte layout of the struct was fixed and known, that made sense.

有关一些背景这也是有趣的阅读的 c语言的发展的由丹尼斯里奇约C. C'S predecessor ​​BCPL没有任何阵列的起源;内存与指针只是齐次线性内存到它。

For some background it's also interesting to read The Development of the C Language by Dennis Ritchie about the origins of C. C's predecessor BCPL didn't have any arrays; the memory was just homogeneous linear memory with pointers into it.

这篇关于为什么用C衰变数组指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆