【问题标题】:Difference between linked list declaration in CC中链表声明的区别
【发布时间】:2012-09-14 04:57:13
【问题描述】:

最近在我的导师关于链表的讲座中,他这样声明它们:

struct asd *head=(struct asd *)malloc(sizeof(struct asd));

我想知道上面的声明和这个有什么区别:

struct asd *head=malloc(sizeof(struct asd));

因为我在创建的每个链接列表中都使用了后者。顺便说一句,语言是 C。

【问题讨论】:

    标签: c casting linked-list malloc


    【解决方案1】:

    基本上没有区别,问题是malloc 返回一个void *,然后可以将其设置为 C 中的任何其他指针类型,在 C++ 中,它需要像最初那样进行显式类型转换,在 C 中它的皱着眉头对 malloc 的返回进行类型转换。

    所以你的导师可能一开始学的是 C++,然后是 C,这实际上现在很普遍。

    【讨论】:

      【解决方案2】:

      以下是正常的,使用C时推荐:

      struct asd *head = malloc(sizeof(*head));
      
      1. 建议使用sizeof(*head) 而不是sizeof(struct asd),因为这样可以减少拼写错误,尤其是在重构代码时。两者在其他方面是等价的。

      2. 不建议投malloc的return,因为这样没有正面作用。在某些情况下,转换 malloc 的结果会产生负面效果,因为当您忘记包含 <stdlib.h> 时,它可以抑制 C99 之前的消息的错误消息。

        李>

      见:Do I cast the result of malloc?

      脚注: 强制转换malloc 的结果的唯一合理原因是您可以编写同时使用 C 和 C++ 的代码。但是请不要写既是 C 又是 C++ 的代码,这有点疯狂。

      【讨论】:

      • 强制转换是指第一个声明。我对 C 术语有点生疏。我也没有计划要同时使用 C 和 C++。我还没有准备好去精神病院。无论如何感谢您的回答。
      【解决方案3】:

      malloc 返回一个 void* 指针,因此您的讲师使用了正确的语法并显式转换为正确的类型。您所做的工作有效,因为编译器会自动为您转换它。我假设您使用了 MSVC,因为 GCC 会警告您(我认为)。

      【讨论】:

      • 不,从void * 到任何数据指针类型的隐式转换不应导致任何编译器发出警告。也许您正在考虑 C++?
      • 是的,我确实想到了 C++。 ANSI C 和 C99 是一样的吗?
      • “ANSI C”你可能想说 C90 或 C89,因为 C99 也是一个 ANSI 标准。所有具有void * 的C 版本都允许将其隐式转换为任何数据指针类型,这就是void * 首先存在的全部原因。旧的 C 版本没有 void * 和 malloc 返回 char *,所以强制转换是必要的……但这些确实是旧的 ANSI 之前的版本。
      【解决方案4】:

      其实没什么区别。 Malloc 分配特定大小的内存(结构 asd 的字节数)。这两种情况都会发生。不同之处在于指针(只是一个内存地址)在第一个示例中被强制转换,而不是在第二个示例中强制转换。

      投射指针实际上并没有“做任何事情”。它是一种语法糖,旨在使您(和编译器)更容易以特定方式思考指针。同样,在此示例中,它没有任何区别。

      我个人更喜欢您的讲师使用的第一种方法,因为它是明确的。您明确表示 malloc 返回的内存地址指向struct asd。尽管在内部,指针是指针是指针。在 C 中,显式几乎总是一件好事。

      【讨论】:

      • 第一种方法在pre-C99编译器中忘记包含<stdlib.h>不会产生错误,而且还会重复代码,所以一般不赞成强制转换malloc的结果在 C 中。在 C 中,过于明确通常是一个坏主意,因为它会抑制警告,因为编译器相信如果您过于明确,您就会知道自己在做什么。
      • @DietrichEpp:我很明确,因为我相信开发人员应该考虑正在发生的自动转换并与编译器一起工作以产生预期的结果。我鼓励新开发人员非常注意自动行为:在我看来,开发人员是否选择显式是个人偏好。
      • 另一方面,编译器将检查任何隐式转换的正确性,但不会检查显式转换。检查显式转换正确性的唯一方法是让人类观察并思考片刻,但使用隐式转换,编译器能够捕获大量错误。这里的主要例外是对无符号整数的隐式强制转换,这通常会产生令人惊讶的结果。使用显式转换通常是一种在本地禁用诊断的简单方法。
      【解决方案5】:

      malloc() 返回一个 void 指针,在 C 中,可以将 void 指针分配给任何指针,而无需显式强制转换。所以不需要显式转换(#1)。

      事实上,一些程序员会建议避免使用强制转换 (#2) 以避免出现模糊的可用性错误。

      如果您忘记包含stdlib.h。编译器将假定malloc() 是一个返回int 的函数,并且由于显式转换,将malloc() 返回的void* 指针转换为int。在某些平台上,int 的大小和指针的大小可能不同,因此这种不希望的类型转换可能会导致数据损坏。

      就我个人而言,我不认为这是一个很大的原因,而是与古老的Yoda condition类似的哲学。

      【讨论】:

        猜你喜欢
        • 2023-03-18
        • 2010-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-10
        • 2020-06-07
        • 2011-02-23
        相关资源
        最近更新 更多