【问题标题】:Why do we cast return value of malloc? [duplicate]为什么我们要转换 malloc 的返回值? [复制]
【发布时间】:2013-12-04 08:30:17
【问题描述】:

有人可以向我解释为什么有些程序员在 malloc 前使用 (char*) 吗?我知道它返回 void 但为什么我希望它只返回 char 内存?对不起,我只是编程的新手。谢谢

【问题讨论】:

标签: c malloc


【解决方案1】:

不需要转换malloc的返回值,因为它的返回类型是void*

谁能解释一下为什么有些程序员在 malloc 前面使用(char *)

他们做错了(很可能)通过强制转换(在优秀的程序员看来)。

正如wiki所说:

malloc 返回一个 void 指针 (void *),表示它是一个指向未知数据类型区域的指针。 由于强类型系统,在 C++ 中需要使用强制转换,而在 C1 中并非如此。根据一些程序员的说法,malloc 缺少返回的特定指针类型是类型不安全的行为:malloc 基于字节数而不是类型进行分配。这与 C++ new operator 不同,后者返回一个类型依赖于操作数的指针。 可以将此指针“强制转换”为特定类型:

int *ptr;
ptr = malloc(10 * sizeof (*ptr));               /* without a cast */
ptr = (int *)malloc(10 * sizeof (*ptr));        /* with a cast */
ptr = reinterpret_cast<int *>(malloc(10 * sizeof (*ptr))); /* with a cast, for C++ */
  

执行这样的演员阵容有利有弊

铸造的优点:

  • 包含强制转换允许程序或函数编译为 C++
  • 演员表允许 1989 年以前版本的 malloc 最初返回 char *
  • 如果目标指针类型发生变化,特别是在声明的指针远离malloc() 调用时,转换可以帮助开发人员识别类型大小的不一致。

铸造的缺点:

  • 根据 ANSI C 标准,转换是冗余的
  • 添加转换可能会掩盖包含标头 stdlib.h 的失败,其中找到了 malloc 的原型。在没有malloc 的原型的情况下,标准要求C 编译器假定malloc 返回一个int。如果没有强制转换,则在将此整数分配给指针时发出警告;但是,使用演员表时,不会产生此警告,从而隐藏了一个错误。在某些架构和数据模型上(例如 64 位系统上的 LP64,其中 long 和指针为 64 位,int 为 32 位),此错误实际上可能导致未定义的行为,因为隐式声明的 malloc 返回一个32 位值,而实际定义的函数返回 64 位值。根据调用约定和内存布局,这可能会导致堆栈粉碎。这个问题在现代编译器中不太可能被忽视,因为它们一致地产生警告,指出使用了未声明的函数,因此仍然会出现警告。例如,GCC 的默认行为是显示一条警告,内容为“内置函数的不兼容隐式声明”,无论是否存在强制转换。
  • 如果更改了指针的类型,则必须修复调用和转换 malloc 的所有代码行(除非它被转换为 typedef)。

1。重点是我的。

【讨论】:

  • 您的最后一点实际上可能是也可能不是劣势。如果指针的类型可能会以需要检查所有分配它的位置的方式更改(例如,因为可能需要调整大小),则需要更改带有malloc 的行的事实可能是一件好事。
  • @supercat;是的,这可能是一件好事,但同时也可能是可悲的。
  • 在对malloc() 的调用中确保为sizeof 使用正确类型的更好方法是完全 使用类型,而是使用表达式: sizeof *pointer 不易出错。因此,第三个“优势”被否定了。
【解决方案2】:

由于 malloc 的返回类型为 void*,当您将结果分配给指针时,它会隐式转换为新类型。因此,不需要显式转换。实际上,不鼓励使用显式转换,如 here 所述。

【讨论】:

    【解决方案3】:

    ma​​lloc 返回 void*,这是一个通用指针,可以指向任何类型的数据。 (char*) 是一种显式类型转换,将 malloc 返回的指针从指向任何东西的指针转换为指向 char 的指针。这在 C 中是不必要的,因为它是隐式完成的,实际上建议不要这样做,因为它可以隐藏一些错误。

    如果您也需要将代码编译为 C++ 而不仅仅是 C,那么您将需要显式转换,因为 C++ 不执行隐式转换。

    【讨论】:

      【解决方案4】:

      malloc() 返回一个void*,因为malloc() 不知道它的调用者将如何使用它在堆上分配的内存。 所以这取决于你,调用者将(void*) 转换为你想在内存中使用的适当类型的指针。 (int*) 存储整数。 (char*) 存储字符等。

      话虽如此,您不必显式地强制返回 malloc() 调用。在某些情况下,这样做可能会导致错误。

      请在此处阅读问题

      What's wrong with casting malloc's return value?

      Specifically, what's dangerous about casting the result of malloc?

      【讨论】:

        猜你喜欢
        • 2010-12-10
        • 2010-10-31
        • 2011-01-09
        • 1970-01-01
        • 1970-01-01
        • 2019-06-14
        • 2013-09-18
        相关资源
        最近更新 更多