函数参数中的空指针

void pointer in function parameter

本文关键字:空指针 参数 函数      更新时间:2023-10-16

请考虑以下程序:

#include <iostream>
void f(void* a)
{
    std::cout<<"(void*)fun is calledn";
    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*而不是正确的指针类型int*,您明确告诉编译器不要告诉您是否错误地使用类型或以未定义的方式使用。

因为调用函数的正确方法是f(b)对吧?

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

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

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

void f(void* a)

声明意味着应该传递一些指针,并且不进行其他限制。

void*可以捕获任何类型的指针,void**也不例外

好的。

根据要求。

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

然后上床睡觉再想一想。

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

如果你愿意,可以反对我。

使用类型具有编译器可以为您检查内容的奢侈。 例如,事物是如何相关的。如何处理该对象。

但是使用虚空指针,你完全靠自己。祝你好运

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

First

你可以有一个void*点来void**.您的代码是显示void*指针有多危险的众多示例之一。

第二

对于类型转换,您应该使用:

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

而不是您正在使用的 C 样式转换:

void*b = (int*)&a;

如果我像这样更改函数调用语句: f(&b); 它仍然编译良好并在运行时崩溃。为什么?

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

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

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

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

// A function that accepts a void pointer
void f(void* a)
{
    std::cout<<"(void*)fun is calledn";
    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);
}