【问题标题】:Casting void pointers铸造空指针
【发布时间】:2011-04-03 08:17:33
【问题描述】:

我在旧的 C 代码中看到了很多以下内容:

type_t *x = (type_t *) malloc(...);

既然是void *,那么转换从malloc() 返回的指针有什么意义?是不是因为旧的 C 编译器不支持 void 指针,而 malloc() 过去常常返回 char *

【问题讨论】:

  • C 允许这样做,而 C++ 不允许。但是,这并不一定意味着您应该在使用 C 编程时转换 void*。C 不是 C++。
  • 我在这里问了一个类似的问题:stackoverflow.com/questions/605845/…

标签: c pointers void-pointers


【解决方案1】:

你自己的解释是正确的。 Pre-ANSI C ('K&R' C) 没有带有隐式转换的 void * 类型。 char * 兼作伪 void * 类型,但您需要显式转换类型转换。

在现代 C 中,强制转换是不受欢迎的,因为它可以抑制编译器对缺少 malloc 原型的警告。在 C++ 中,需要进行强制转换(但在大多数情况下,您应该使用 new 而不是 malloc)。

更新

我下面试图解释为什么需要演员表的 cmets 有点不清楚,我会在这里尝试更好地解释它。您可能会认为即使malloc 返回char *,也不需要强制转换,因为它类似于:

int  *a;
char *b = a;

但在此示例中,还需要强制转换。第二行是简单赋值运算符 (C99 6.5.1.6.1) 的约束冲突。两个指针操作数都必须是兼容类型。当您将其更改为:

int  *a;
char *b = (char *) a;

约束冲突消失(两个操作数现在都具有char * 类型)并且结果是明确定义的(用于转换为字符指针)。在“相反的情况”中:

char *c;
int  *d = (int *) c;

同样的参数适用于强制转换,但当int *char * 有更严格的对齐要求时,结果是实现定义

结论:在 ANSI 之前的日子里,类型转换是必要的,因为 malloc 返回 char * 并且不转换结果是违反 '=' 运算符的约束。

【讨论】:

  • 我也认为这个论点是最有道理的。然而,即使 malloc() 返回 char *,这种转换在技术上也不是必需的,因为左值的类型无论如何都无法更改。
  • @Blagovest K&R2 (p142) 说强制转换是必要的,但勘误表 (cm.bell-labs.com/cm/cs/cbook/2ediffs.html) 撤回了这一点并补充说:“另一方面,在 ANSI 之前,强制转换是必要的,并且它也在 C++ 中。”
  • 我的评论试图解释 char *c;诠释* x; x = c;除了你会从编译器得到的警告之外,在技术上是可以的。
  • 我认为你错了,因为对齐问题:从 C99 6.3.2.3 (7) 开始:“指向对象或不完整类型的指针可能会转换为指向不同对象或不完整类型的指针. 如果结果指针未正确对齐指向的类型,则行为未定义。"
  • @Blagovest Buyukliev: x = c 根本不需要编译——它违反了标准中的“shall”条款。编译器将其作为错误拒绝而不只是发出警告是合法的。
【解决方案2】:

这里的问题是与C的任何方言都不兼容。问题是C++。在 C++ 中,void 指针不能自动转换为任何其他指针类型。因此,如果没有显式转换,这段代码将无法使用 C++ 编译器进行编译。

【讨论】:

    【解决方案3】:

    我不知道 malloc 曾经返回一个 char*。

    但并不总是允许从 void* 隐式转换为 type_t*(或任何其他类型)。 因此,需要显式转换为正确的类型。

    【讨论】:

    • 在 C89 之前,malloc() 返回 char *void * 类型是在 C89 中引入的,正是因为需要一种可以隐式转换为任何其他指针类型的“通用”指针类型。从 C89 开始,没有理由显式转换 malloc() 的结果。
    • 我的立场是正确的。我从不知道 malloc 曾经返回 char* 。很高兴知道。
    【解决方案4】:

    既然 malloc() 返回的指针是 void *,那么转换它的意义何在?

    恰恰相反。您需要将 void 指针强制转换为实际类型,然后才能使用它,因为void * 不表示存储在该位置的数据。

    【讨论】:

    • 我并不想在不强制转换的情况下取消引用 void 指针。这里的重点是左值是一个类型化的指针,你仍然需要在赋值之前转换右值。
    • 一个void*会在赋值时自动转换成对应的type_t*
    • 您的论点只说明了为什么 x(在 OP 中)必须是 type_t*,而不是为什么必须进行强制转换才能在那里分配值。
    • -1 表示“cast”一词的错误使用,它指的是 C 中的 (type) 运算符。在使用指针之前确实需要进行转换,但它会隐式发生。
    猜你喜欢
    • 2011-03-26
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2018-04-07
    相关资源
    最近更新 更多