函数参数中的空指针

void pointer in function parameter

考虑以下程序:

#include <iostream>
void f(void* a)
{
    std::cout<<"(void*)fun is called\n";
    std::cout<<*(int*)a<<'\n';
}
int main()
{
    int a=9;
    void* b=(int*)&a;
    f(b);
    return 0;
}

如果我像这样更改函数调用语句:

f(&b);

它仍然可以正常编译并在运行时崩溃。为什么?是什么原因?我不应该得到编译时错误吗?因为函数的正确调用方式是f(b)。正确的?另外,为什么允许将 NULL 传递给参数类型为 (void*) 的函数?

如有遗漏或理解有误,请指正。

void*可以捕获任何类型的指针,void**

也不例外

第一

您可以 void* 指向 void**。您的代码是显示 void* 指针有多危险的众多示例之一。

第二

你应该使用类型转换:

void* b = static_cast<int*>(&a);

而不是您正在使用的 c 风格转换:

void*b = (int*)&a;

It still compiles fine & crashes at runtime. Why? What is the reason?

因为void*是一种删除所有类型安全和类型检查的技术。

Should I not get the compile time error?

通过使用 void* 而不是正确的指针类型 int*,您明确告诉编译器 如果您使用的是类型,则不要告诉您不正确或未定义的方式。

Because the correct way to call the function is f(b). right?

这就是您的函数 声明内容 不一致的地方。

    std::cout<<"(void*)fun is called\n";
    std::cout<<*(int*)a<<'\n';

上面的内容暗示应该传递指向int的指针:

void f(void* a)

这个声明意味着应该传递一些指针,没有其他限制。

好的。

根据要求。

不要使用 void 指针,除非你想不出任何其他解决方法。

然后上床再想一想。

空指针使程序员可以忘记类型。这意味着编译可以放弃简单的检查。这在我看来也意味着程序员已经失去了情节。

如果你愿意,请给我投反对票。

使用类型可以让编译器为您检查一切。例如。事物是如何相关的。如何对待那个对象。

但是使用 void 指针你就只能靠自己了。祝你好运

你不会得到编译时错误,因为 f(&b) 调用 f 并将 b 的地址作为参数传递,然后将其转换为 void* .您会收到运行时错误,因为那时您正试图将指向整数的指针转换为整数。 但是,是的,正如其他人所说,这样做非常糟糕。

If I change the function call statement like this: f(&b); It still compiles fine & crashes at runtime. Why?

您的函数 f(void*) 将毫无怨言地接受指向任何类型的指针。任何指针都会悄悄地转换为 void 指针。指向指针的指针仍然是指针。所以你的第二个案例确实编译得很好。然后它崩溃了。也许。

在第一种情况下,您将一个指向 int 的指针转换为一个指向 void 的指针,然后再转换回一个指向 int 的指针。通过 void*(以及通过 char*)的那些往返转换必须有效。在第二种情况下,您从 void** 转换为 void*,再转换为 int*。现在你正在调用未定义的行为。什么都可以。在我的电脑上,我的编译器,你的代码运行得很好。它打印垃圾。我很确定你的代码不会擦除我的硬盘,但它可以。任何事情都伴随着未定义的行为。不要调用未定义的行为。

支持void*的原因是历史性的。有很多使用 void 指针的旧 C 和 C++ 代码。 唯一 编写使用空指针的新 C++ 代码的原因是,如果您需要与那些使用空指针的旧函数之一进行交互。

我发现自己在这里是因为我正在做一项要求相同功能的家庭作业。结合每条评论后,这就是我想出的。

// A function that accepts a void pointer
void f(void* a)
{
    std::cout<<"(void*)fun is called\n";
    std::cout<< "value for a: " << *(int*)a << '\n';
}


int main() {
    int a = 9;
    void* c = static_cast<int*>(&a);

    int b = 3;
    f(&b);
    f(c);
}