2012-03-12 104 views
0

我有以下代码:为什么指针不能分配给C中的数组?

int *pa; 

int a[3] = {1, 2, 3}; 

为什么PA =被确定,但A = PA是不允许的?

+0

,你会想到什么'一= pa'办? – 2012-03-12 13:33:35

+0

编译器认为这是一个错误,一个错字。我同意。你为什么要将一个数组声明为一个数组,然后突然将它指向它的数据?如果你想要这样的功能,你会创建一个指针来代替,所以它没有任何意义。 – user1227804 2012-03-12 13:40:35

+0

可能重复[数组名称是一个指针在C?](http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c) – 2012-03-12 18:08:42

回答

6

的主要区别是该类型的a仍然是一个数组,但它只是衰变为指针,当你做pa=a;pa现在将指向第一个数组的元素不是整个数组本身。当你做a=pa它没有任何意义,因为你正在尝试指向一个数据类型,它将3个整数保持为只能指向一个整数的类型。

0

注意:这纯粹是概念性的,这不是发生这种情况的真正原因。

我喜欢考虑指针分配,如OOP &继承。

想象一下int *是一个通用对象。现在,将int []视为从int *继承的对象。你可以看到,你可以从int []下降到int *,但不能向上投射。

+0

虽然我理解类比,我不知道认为将这个问题与其实际上并不相容的东西混淆是有帮助的。 – 2012-03-12 13:57:15

+0

@OliCharlesworth真的,这就是为什么我添加了最初的声明,它是纯粹的概念。 – 2012-03-12 14:07:20

0

那么,简单的答案是,语言定义根本不允许它 - 这是一个设计选择。

Chapter and verse

6.5.16赋值运算符
...
约束

2赋值操作员有修改的左值作为其左操作数。

什么是可修改的左值?

6.3.2.1左值,数组和功能指示器

1所述的 左值是与对象类型或大于 void以外的不完全类型的表达式; 53) 如果左值在评估时未指定对象,则行为是未定义的。 当一个对象被称为具有特定类型时,该类型由用于指定该对象的左值指定。 A 可修改的左值是一个左值,它没有数组类型, 没有不完整类型,没有const限定类型,并且如果它是结构体 或union,没有任何成员包括递归地包含 的任何成员或元素,都包含聚合或联合)。
...53)名称“左值”最初来自赋值表达式 E1 = E2,其中左边的 操作数 E1需要是(可修改的)左值。它可能更好地被认为是代表对象的'定位器值'的 。有时称为“右值”的是在该国际标准中将 描述为“表达式的值”。

强调添加。

C中的数组表达式的处理方式与大多数其他表达式不同。原因解释在article丹尼斯里奇写了关于C语言的发展:

NB存在这么简单,没有完整的描述写了。它提供的类型 intchar,它们的阵列,和指向它们的指针,在由
 

    int i, j; 
    char c, d; 
    int iarray[10]; 
    int ipointer[]; 
    char carray[10]; 
    char cpointer[]; 
 
阵列的语义为代表的样式声明仍然保持着原样在B和BCPL:的 iarray动态初始化的声明和 carray创建细胞其值分别指向10个整数和字符序列中的第一个。 ipointercpointer的声明省略了大小,以声明不应自动分配存储空间。在过程中,语言对指针的解释与数组变量相同:指针声明创建了一个与数组声明不同的单元格,只是程序员需要分配一个指示对象,而不是让编译器分配空间,初始化单元格。

存储在绑定到数组和指针名称的单元格中的值是相应存储区域的以字节为单位的计算机地址。因此,通过指针间接寻址意味着没有运行时间开销来将指针从字到字节偏移量缩放。另一方面,用于数组下标和指针算术的机器代码现在取决于数组或指针的类型:计算 iarray[i]ipointer+i暗指将加数i按照所引用对象的大小缩放。

这些语义代表了从B的简单转换,并且我在几个月内对它们进行了实验。当我尝试扩展类型符号时,特别是添加结构化(记录)类型时问题变得明显。看起来,结构应该以直观的方式映射到机器的内存中,但是在包含数组的结构中,没有合适的地方来隐藏包含数组基的指针,也没有任何方便的方式来安排它初始化。例如,早期Unix系统的目录条目可能在C中被描述为

    struct { 
     int inumber; 
     char name[14]; 
    }; 
我希望结构不仅仅描述一个抽象对象的特征,而且要描述可能从目录中读取的位的集合。编译器在哪里可以隐藏语义要求的指针 name?即使结构被认为更抽象,并且指针的空间可能以某种方式隐藏起来,在分配复杂对象时如何处理这些指针正确初始化的技术问题,可能是指定包含含有任意深度结构的数组的结构的一个结构?

该解决方案构成了无类型BCPL和类型C之间的进化链中的关键跳跃。它消除了存储器中指针的具体化,而是在表达式中提到数组名称时导致创建指针。在今天的C中存活的规则是数组类型的值在它们出现在表达式中时被转换成指向构成该数组的第一个对象的指针。

尽管语言的语义发生了根本的变化,但是本发明使大多数现有B代码能够继续工作。很少的程序为数组名称分配新值以调整它的原点(可能在B和BCPL中使用,在C中毫无意义)很容易修复。更重要的是,新语言保留了对数组语义的一致和可行的(如果不寻常的)解释,同时为更全面的类型结构开辟了道路。

这是一个很好的文章,并很值得一读,如果你感兴趣的C.

的“为什么”
相关问题