【问题标题】:What wording in the C++ standard allows static_cast<non-void-type*>(malloc(N)); to work?C++ 标准中的哪些措辞允许 static_cast<non-void-type*>(malloc(N));去工作?
【发布时间】:2011-02-06 13:10:07
【问题描述】:

据我了解 5.2.9 静态转换中的措辞,唯一允许 void*-to-object-pointer 转换的结果是 void* 是第一名。

在整个标准中,有一堆对指针表示的引用,void 指针的表示与 char 指针的表示相同,依此类推,但似乎从未明确假设强制转换一个任意的void 指针会产生一个指向内存中相同位置的指针,但类型不同,就像类型双关是未定义的,而不是双关回到对象的实际类型。

因此,虽然malloc 清楚地返回了合适内存的地址等,但据我所见,似乎没有任何方法可以实际使用它,可移植。

【问题讨论】:

  • 一个得到很好接受答案的相关问题:stackoverflow.com/questions/1863069/…
  • 我希望有一个更明确的答案,涉及更少的解释和挥手。毕竟,static_cast 应该比推理 reinterpret_cast 更简单。
  • 我怀疑是否有更少“挥手”和解释的答案(不确定您所说的“挥手”是什么意思)。 Stadnard有时很少有故意的绝对保证。这暗示 static_cast&lt;nonvoid*&gt;(voidptr) 只是工作并产生原始值,没有明确的措辞。实现没有理由更改该值,但标准也没有明确禁止它。想要表现得怪异的实现已经被允许在最简单的事情上崩溃(超过实现限制)。
  • @JohannesSchaub-litb "只是工作并产生原始值,没有明确的措辞" "对象指针类型的值转换为“指向 cv void 的指针”并返回,可能具有不同的 cv 限定,应具有其原始值。”

标签: c++ malloc language-lawyer static-cast object-lifetime


【解决方案1】:

C++0x 标准草案在 5.2.9/13 中有:

“指向 cv1 的指针”类型的右值 void”可以转换为右值 键入“指向 cv2 T 的指针”,其中 T 是 对象类型和 cv2 相同 cv 资格为或更高 cv-qualification 比,cv1。空 指针值转换为 null 目标类型的指针值。 指向对象的类型指针的值 转换为“指向 cv void 的指针”和 回来,可能有不同的 简历资格,应有其 原值。

但还要注意,强制转换不一定会产生有效的对象:

 std::string* p = static_cast<std::string*>(malloc(sizeof(*p)));
 //*p not a valid object 

【讨论】:

  • malloc 不会将指针对象类型的值转换为指针空值;它只是给你一个指向空指针类型的指针。因此,我认为 5.2.9/13 的最后一句话不适用。
  • 我也是。我的意图是在我的问题中提到这句话,并指出我认为它在这种情况下没有帮助。此外,我对取消引用指针的部分不感兴趣,但更多的是首先获取它。
  • 最后一句不适用,因为没有来回转换,没有原值。我不明白为什么其余的不应该适用。 - 不是简单地说:void* 可以静态转换为T*;如果指针为NULL,没关系;如果 void* 最初是 T* 那就太棒了。
  • 我同意,我认为标准中没有更好的措辞。我认为@ben 正在寻找最后一句话包含的保证like,但我认为没有。
  • 但是它没有说明结果值是什么。对于其他转换,它明确表示,例如“float 类型的右值可以转换为 double 类型的右值。值不变”
【解决方案2】:

C++03,§20.4.6p2

内容与标准 C 库头文件 相同,但有以下更改:[此处不适用的更改列表]

C99,§7.20.3.3p2-3

(虽然C++03是基于C89,但我只有C99可以引用。不过,我相信这部分在语义上没有改变。§7.20.3p1也可能有用。)

malloc 函数为大小由 size 指定的对象分配空间, 其值是不确定的。

malloc 函数返回空指针或指向分配空间的指针。

从这两个引号中,malloc 分配一个未初始化的对象并返回一个指向它的指针,或者返回一个空指针。作为 void 指针的指向对象的指针可以转换为指向该对象的指针(C++03 §5.2.9p13 的第一句,在上一个答案中提到)。


这应该少一些你抱怨的“挥手”,但有人可能会争辩说我是在“解释”C 对 malloc 的定义,例如,注意到 C 说的是“分配的空间”而不是“到分配的对象”。对于那些人:首先要意识到“空间”和“对象”在 C 中是同义词,其次请向标准委员会提交缺陷报告,因为即使我也不够迂腐,无法继续。 :)

我会告诉你这个疑问的好处,并相信你在标准之间的交叉引用、交叉解释和有时令人困惑的集成中被绊倒了,而不是“空间”与“对象”。

【讨论】:

    【解决方案3】:

    在整个标准中有一堆对指针表示的引用,void指针的表示与char指针的表示相同

    是的,确实。

    因此,虽然 malloc 清楚地返回了合适内存的地址等,但据我所见,似乎没有任何方法可以实际使用它,可移植。

    当然有:

    无效 *vp = malloc (1); 字符 *cp; memcpy (&cp, &vb, sizeof cp); *cp ='';

    有一个小问题:它不适用于任何其他类型。 :(

    【讨论】:

    • IRC 你可以使用placement new。
    • @DanM。是的,当然您可以使用具有特定 C++ 语法的 C 库函数。这样就失去了使用 C/C++ 语法访问 C 库的全部意义,并且整个 C/C++ 兼容性对于非平凡代码。能够使用合理的 C 代码而很少或没有更改被明确列为 C++ 的初始设计以及 C++ 标准委员会的使命宣言。我知道现在有些人鄙视在 C++ 中有效的 C 程序子集,并将任何试图保留 C/C++ 子集的尝试视为浪费时间、落后思维等。他们是非常错误的。
    猜你喜欢
    • 2014-07-21
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多