繁体   English   中英

如何打印void指针指向的变量

[英]How can I print the variable that a void pointer points to

我希望函数根据不同的参数值返回不同的类型,但是如何在main()打印void指针指向的变量?

#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
     if (a == 1)
     {
     int param = 5;
     return &param;
     }
     else if (a == 2)
    {
    double param = 5.5;
    return &param;
    }
    else if (a == 3)
    {
    string param = "hello";
    return &param;
    }
    else
    {
    return nullptr;
    }
}
int main()
{

    void *ptr = func(3);//

    cout << ptr;// print the address not the value
    getchar();
    return 0;
 }     

param是一个自动变量。 您不能将其退回并在其范围之外使用它。

param仅存在于func ,如果返回,结果为Undefined Behavior。

要修复它,您可以:

  • 动态地在堆上分配param 执行此操作后,您可以安全地返回param地址,但您必须记住在不需要它时将其释放。

这是对代码的更正

#include <iostream>
#include <string>
#include <string.h>

using namespace std;

void * func(int a)
{
    if (a == 1)
    {
        int *param = new int(5);
        return param;
    }
    else if (a == 2)
    {
        double *param = new double(5.5);
        return param;
    }
    else if (a == 3)
    {
        char *param = new char[50];
        strcpy(param, "test");
        return param;
    }

    return nullptr;
}

int main()
{
    int *ptr = (int*)func(1);
    cout << *ptr << std::endl;         // print the int value
    delete ptr;

    double *ptr2 = (double*)func(2);
    cout << *ptr2 << std::endl;        // print the double value
    delete ptr2;

    char *ptr3 = (char*)func(3);
    cout << ptr3 << std::endl;        // print the string
    delete[] ptr3;

    getchar();
    return 0;
 }

如果你可以使用C ++ 17,你可以通过使用std::variant而不是void *来轻松解决它:

#include<iostream>
#include<string>
#include<variant>

std::variant<int, double, std::string, void *> func(int a) {
     if (a == 1) {
         int param = 5;
         return param;
     } else if (a == 2) {
        double param = 5.5;
        return param;
    } else if (a == 3) {
        std::string param = "hello";
        return param;
    } else {
        return nullptr;
    }
}

int main() {
    std::visit([](auto v) {
        std::cout << v << std::endl;
    }, func(3));
}

wandbox上查看并运行

在C ++ 11/14中,您可以使用带标记的联合执行相同的操作。 基本的想法是,您返回的内容包含足够的信息,以便调用者可以从中获取原始类型。


存在替代方案。
例如,您可以擦除类型并返回包含原始(已擦除)变量和指向函数的指针的对,该函数填充了函数模板的实例。 后者将能够从void *重建原始变量,因为它知道它的类型。
好吧,几乎是一个很棒的机器,你可以避免使用带标记的union或std::variant (在一天结束时或多或少是类型安全版本的标记联合)。

你要返回的是局部变量的地址。 当函数返回时,该变量超出范围,这意味着它正在使用的内存可以重用。 尝试取消引用该指针(即访问它指向的内存)会调用未定义的行为

即使您返回一个有效的指针,您的函数返回void *的事实意味着有关该指针指向的内容的任何类型信息都将丢失。 您可以从该地址开始打印一个或多个字节,但它不会告诉您原始类型是什么。

即使该指针有效,您也无法获得足够的信息来强制转换为某些东西,然后将其打印出来。 没有关于其大小的信息,没有其内部布局的信息。 所以,你根本无法打印void *指向的内容,除非你手边有一些手工准备的信息,并强制static_cast为已知类型。 例如:

double x = 1.2;
int y = 5;
int f(void** output) {
    static int x;
    if ( x++ ) {
        *output = &x;
        return 1;
    }
    *output = &y;
    return 2;
}

...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));

暂无
暂无

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

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