【问题标题】:Passing C++ void pointers [duplicate]传递 C++ void 指针 [重复]
【发布时间】:2019-12-13 08:22:37
【问题描述】:

我对 void 指针感到困惑。尽管此代码片段可以编译,但在函数 f2 中取消引用变量 c 的行为是否未定义?

#include <cstdlib>
#include <cstdio>

void f2(void* c) {  // legal/stupid
    // although this compiles, is dereferencing c here undefined behaviour?
}

void f1(void** b) {
    printf("%d\n", *(int*)*b);
    f2(b);
}

int main() {    
    int i{ 5 };
    void* a{ (void*)&i };
    f1(&a);
    return 0;
}

【问题讨论】:

  • 用花括号初始化变量有什么特别的原因吗?此外,最好在问题中包含您认为此代码调用 UB 的原因... :)
  • 你不能取消引用空指针。
  • 除非您必须使用 C API,否则我建议您远离 void 指针。 C++ 有一个非常好的类型系统,模板取代了对 void 指针的需求。
  • @NeilButterworth 是 right,但我认为 OP 并不是故意要问这个的。我猜 .. :)
  • @sid 你有什么理由在 C++ 中搞乱原始指针?

标签: c++ void-pointers


【解决方案1】:

void* 转换回原始类型的指针是不是未定义的行为:

int a = 10;

void* b = (void*)&a;

int* c = (int*)b;

int d = *c; //d == 10 now; this is fine

因此,如果 f2 在使用之前将 c 转换为 void**,则代码将是明确定义的。如果f2 尝试将c 转换为其他东西(例如,如果f2 将c 转换为int*,即使它被赋予了void**),则未定义行为。

几乎唯一的例外是转换为char*:保证没问题。

话虽如此,因为在使用 void* 指针时没有类型安全性,如果可能的话,你应该使用其他东西。

这意味着:

void f2(void* c) {
    void** b = (void**)c;         // Get original void**
    void* b_value = *b;           // Dereference to get void*
    int* int_ptr = (int*)b_value; // Get int* pointer

    int value = *int_ptr;         // Use it
}

是安全的,当且仅当 c 表示指向 void* 的指针,而 void* 本身就是 int*

【讨论】:

    【解决方案2】:

    您的代码会导致未定义的行为。

    以下片段取自C11第 §6.2.5 章:

    void 类型包含一组空值;这是一个不完整的 无法完成的对象类型。

    这意味着指向 void 的指针是一个无效的解引用操作数。

    【讨论】:

    • OP 询问的是 C++,而不是 C。
    猜你喜欢
    • 2013-10-19
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多