繁体   English   中英

如果我们总是 static_cast<> 使用 void* 而不是任何指针类型是否有效?

[英]Is it valid to use void* rather than any pointer type if we always static_cast<> it?

假设我们有以下代码:

struct VeryComplexStruct {
  // a very complex struct

  void test() {}
};

void foo(VeryComplexStruct **ptr) {
  // do something
}

int main() {
  VeryComplexStruct *p = nullptr;
  foo(&p);
  p->test();
}

我想知道如果我们只使用void*并像这样强制转换代码,C++ 标准的代码是否仍然有效:

struct VeryComplexStruct {
  // a very complex struct

  void test() {}
};

void foo(VeryComplexStruct **ptr) {
  // do something
}

int main() {
  void *p = nullptr;
  foo(reinterpret_cast<VeryComplexStruct **>(&p));
  (static_cast<VeryComplexStruct *>(p))->test();
}

如果我们在C++中使用C库,则可能会发生这种情况。 任何想法?

如果代码仍然有效

所呈现的代码(忽略p指向 nullptr 并假设p指向有效的VeryComplexStruct对象)是有效的 - 您可以在指针值之间进行转换。 但是,如果您要访问指针:

struct VeryComplexStruct {
    void test() {}
};

void foo(VeryComplexStruct **ptr) {
  *ptr; // this here
}

int main() {
  void *p = new VeryComplexStruct();
  foo(reinterpret_cast<VeryComplexStruct **>(&p));
  (static_cast<VeryComplexStruct *>(p))->test();
}

那将是无效的-您无法使用VeryComplexStruct **句柄访问void **指针,因此它有点违背了整个目的。 您必须使用void **句柄访问void ** ,例如reinterpret_cast<VeryComplexStruct*>(*reinterpret_cast<void**>(ptr))

任何想法?

Static 类型化语言是一项帮助您处理类型的功能 - 使用void *您将把它全部扔掉 window。 坚持类型,只在需要时转换为void *

reinterpret_cast<VeryComplexStruct **>(&p)

不保证void*VeryComplexStruct*的 alignment 要求兼容。 如果它们不是并且&p没有为VeryComplexStruct*适当地对齐,那么这个转换产生的值将是未指定的,并且基本上以任何方式使用它都会导致未定义的行为。

即使满足 alignment 要求,生成的指针也可能无法用于访问它指向的 object。 没有VeryComplexStruct* object 与地址&p处的void* object指针可互转换。 因此,转换的结果仍将指向void* object,而不是VeryComplexStruct* object。

通常,通过另一种类型的左值(例如,取消引用的指针)访问一种类型的 object 是一种别名违规,导致未定义的行为,但有一些特定的例外情况,此处均不适用。

(甚至不能保证void*VeryComplexStruct*具有相同的大小和表示形式,尽管实际上通常是这种情况。)


(static_cast<VeryComplexStruct *>(p))->test();

假设 function 没有修改p ,这是试图在 null 指针上调用非静态成员 function ,导致未定义的行为。

如果 function 确实以某种方式修改了p ,这基本上只有首先将参数转换回void**才是合法的,那么这取决于 function 对p做了什么。 如果为p分配了一个指向VeryComplexStruct* object 或某些 object 的指针,则该行有效,该指针与此类指针可相互转换。 否则,成员 function 调用将再次具有未定义的行为。


如果我们在 C++ 中使用 C 库,则可能会发生这种情况。 任何想法?

它在 C 中以相同的方式导致未定义的行为,尽管 object model 和使用的术语不同。 在这种情况下,问题将是void*VeryComplexStruct*不是兼容的类型,因此通过指向VeryComplexStruct*的指针访问void* object 将再次违反别名。 因此,如果在 C 库中使用类似的东西,它已经依赖于未定义的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM