为什么我可以在C中使用数组而不是结构作为标量?

时间:2014-06-09 14:26:07

标签: c arrays pointers structure

在C中,数组变量可以用作标量。例如:

char A[5];
if(A) printf("True\n");

将打印为True。鉴于:

struct S { int i; } s;
if(s) printf("True\n");

实际上无法编译,给出错误:

错误:使用了需要标量的结构类型值

这是为什么?

为什么数组变量可以用作指针而不是结构 变量

谢谢。

编辑:也许这是改写问题的更好方法 为什么C赋予A(标量)意义而不是S?

编辑:我的问题本质上更具哲学性。我试图理解为什么C的设计方式如此。为什么数组会像指针一样,但结构却不是。它们都代表连续的内存块。记忆的结构不同,但为什么要重要。

我对编译失败的原因不感兴趣,我理解(我证明它不是我)。

5 个答案:

答案 0 :(得分:1)

  

为什么数组变量可以用作指针但不能用作结构变量?

数组名称转换为指向其第一个元素的指针。

C11:6.3,2.1:

  

...具有类型''数组类型''的表达式将转换为类型为''指向类型'的指针的表达式,指向数组对象的初始元素而不是左值。

结构不是这样。

答案 1 :(得分:1)

还有一件事:struct是一种聚合类型。指向数组第一个元素的指针是标量类型。

编辑
我认为这可能是重点:

  

struct是一种聚合数据类型,就像数组一样。

     

但是,数组具有某种规则性,而结构却没有   有。数组是一些包含某些东西的数组,都是一样的。   例如。 100个整数的数组。每个数组成员都是一个int。你可以索引   你想用任意的100个整数中的哪一个   表达。这是唯一可能的,因为所有元素都是   相同的尺寸,并按顺序排列。这种观察与此类似   数组索引是指针算术的语句   另一方面,结构是元素可以在其中的聚合   各不相同。它们是按名称引用的,没有   索引的非常量表达式的类比。

来自http://www.cdf.toronto.edu/~ajr/209/notes/struct.html

答案 2 :(得分:0)

CA的值将是指向数组第一个元素的指针。

因此if(A) printf("True\n");表示此指针的值不是0做某事。这是完全合法的C(尽管指向静态数组的指针永远不会是0)。另一方面,S是结构的名称,if (S)没有意义。

答案 3 :(得分:0)

命名数组的符号是指向数组第一项的常量:A等同于&A[0]。而且这个指针不是NULL 您使用该指针而不是int期望的if()表达式,因此它被转换为整数常量。指针不是NULL,因此它变为非零整数,因此满足if()条件并调用print

而你的struct与指针相对,没有默认转换为int,所以不能以类似的方式使用。

答案 4 :(得分:0)

如果问题是为什么struct类型没有时,数组表达式会衰减为指针,答案基本如下:

丹尼斯·里奇(Dennis Ritchie)将C的设计基于一种早期的语言B(go figure)。在B中,当您分配了N个元素的数组时,如

auto arr[N];

编译器将分配N + 1个单元格,其中一个单元格将绑定到标识符arr并且将包含到数组的第一个元素的偏移量,类似于:

           +---+
     arr:  |   | ----+
           +---+     |
            ...      |
           +---+     | 
  arr[0]:  |   | <---+
           +---+
  arr[1]:  |   |
           +---+
  arr[2]:  |   |
           +---+
            ...
           +---+
arr[N-1]:  |   |               
           +---+

Ritchie最初保留了这些语义,但在他将struct类型引入语言时遇到了问题。如果他定义了像

这样的结构
struct foo {
  int inode;
  char name[14];
};

他希望struct foo的一个实例有一个双字节int,紧跟一个14字节的char数组;他不希望数组指针卡在中间。最终他决定完全消除数组指针,并设计语言,以便每当它在源代码中看到数组表达式时(表达式不是sizeof或一元&运算符的操作数),它将转换类型为“T的N元素数组”转换为“指向T的指针”,并将其计算为第一个元素的地址。因此,当您在C中分配N个元素的数组时,您将获得

           +---+      
  arr[0]:  |   | 
           +---+
  arr[1]:  |   |
           +---+
  arr[2]:  |   |
           +---+
            ...
           +---+
arr[N-1]:  |   |               
           +---+

没有单独的arr对象用于将偏移量存储到第一个元素。

此转换操作对于数组是唯一的,这是为什么您可以将数组表达式用作标量(技术上,作为指针)。结构变量本身是类型的实例,而不是struct对象向量的偏移量。

要更深入地了解C的为什么,请查看Ritchie的this essay