【问题标题】:Intrinsical difference between struct and array in CC中结构和数组之间的内在区别
【发布时间】:2011-11-04 04:28:14
【问题描述】:

每个人。

这是我写的一个测试程序。

#include <stdio.h>
#include <stdlib.h>

typedef struct _item {
    int value;
} item , *pItem;

typedef struct _itemcontainer {
    pItem i;
} itemcontainer, *pItemcontainer;

int main(void) {
    item i;
    i.value = 1;

    pItem pi = &i;
    pItem* ppi = &pi;

    itemcontainer ei = {&i};
    pItem* pei = (pItem*)(&ei);

    pItem api[1] = {&i};

    printf("First case: %d\n", (*ppi)->value);
    printf("Second case: %d\n", (*pei)->value);
    printf("Third case: %d\n", (*api)->value);


    return EXIT_SUCCESS;
}

三个 printf 函数的结果是相同的值,即 1。从代码来看,变量eiapi的初始化都是{&i}。所以我猜 pItem* pei = (pItem*)ei 应该可以工作,但是它失败了。谁能告诉我eiapi的区别?这似乎与编译器如何处理结构和数组有关,我不擅长。我需要一个具体的解释。提前致谢。

最好的祝福

呸呸

【问题讨论】:

  • 许多人(包括我自己)认为typedef 指针类型是一种不好的做法。我使用typedef struct name name;,如果你想限制对成员的访问,struct name 可以是一个不完整的类型,所以name * 是一个指针,const name * 是一个指向const 的指针。我认为将语言的给定语法用于指针和consts 之类的东西更清楚,因为命名方案比内置语言语法更容易忘记(并且更难谷歌)。如果你使用name *,优秀的 C 程序员会知道,而不会想到需要清理它。

标签: c arrays struct


【解决方案1】:

不同之处在于,在大多数情况下,数组名称会隐式转换为指向其第一个元素的指针,而结构类型的对象名称则不会。

表达式pItem* pei = (pItem*)api; 可以编译,因为它等价于pItem* pei = (pItem*)(&amp;api[0]);

表达式pItem* pei = (pItem*)ei; 无法编译,因为它试图将结构类型的对象(值)转换为指向某个不相关类型的指针。

您使用的表达式pItem* pei = (pItem*)(&amp;ei); 创建了一个指向结构对象的指针,并将其重新解释为指向pItem 的指针。由于 pItem 是结构的第一个元素,因此它与 ei 位于相同的内存地址,这是有效的。 (这甚至由标准保证,§6.7.2.1/13:“指向结构对象的指针,经过适当转换,指向其初始成员”)

【讨论】:

  • 嗯,众所周知,指针的值的含义是一个内存地址。你能告诉我ei(结构类型的对象)的值的含义吗?
  • @machinarium 该结构的值是它包含的所有内容的值。如果您复制一个包含 10 个整数数组的结构,您将实际复制 10 个整数(加上可能的填充)。
  • 好的,我明白了。指针变量的值是一个十六进制数,这让我相信 ei 的值也是一个十六进制数也是错误的。经过调试,发现Eclipse的Variables视图中eivalue列{...},而不是十六进制数字。现在,我完全明白了。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 2018-07-24
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
相关资源
最近更新 更多