简体   繁体   English

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

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

I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to in main() ? 我希望函数根据不同的参数值返回不同的类型,但是如何在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 is an automatic variable. param是一个自动变量。 You cannot return it and use it outside its scope. 您不能将其退回并在其范围之外使用它。

param exists only within func , if you return it, the result is Undefined Behaviour. param仅存在于func ,如果返回,结果为Undefined Behavior。

To fix it you can either: 要修复它,您可以:

  • allocate param on the heap dynamically. 动态地在堆上分配param After you do that, you can safely return param address but you have to remember to free it when you don't need it. 执行此操作后,您可以安全地返回param地址,但您必须记住在不需要它时将其释放。

Here is correction of your code 这是对代码的更正

#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;
 }

If you can use C++17, you can easily solve it by using a std::variant instead of a void * : 如果你可以使用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));
}

See it up and running on wandbox . wandbox上查看并运行

In C++11/14 you can do the same with a tagged union . 在C ++ 11/14中,您可以使用带标记的联合执行相同的操作。 The basic idea is that what you return contains enough information so that the caller can get out of it the original type. 基本的想法是,您返回的内容包含足够的信息,以便调用者可以从中获取原始类型。


Alternatives exist. 存在替代方案。
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. 例如,您可以擦除类型并返回包含原始(已擦除)变量和指向函数的指针的对,该函数填充了函数模板的实例。 The latter will be able to reconstruct the original variable from a void * for it knows its type. 后者将能够从void *重建原始变量,因为它知道它的类型。
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant (more or less a type-safe version of a tagged union at the end of the day). 好吧,几乎是一个很棒的机器,你可以避免使用带标记的union或std::variant (在一天结束时或多或少是类型安全版本的标记联合)。

What you're returning is the address of a local variable. 你要返回的是局部变量的地址。 That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. 当函数返回时,该变量超出范围,这意味着它正在使用的内存可以重用。 Attempting to dereference that pointer (ie access the memory it points to) invokes undefined behavior . 尝试取消引用该指针(即访问它指向的内存)会调用未定义的行为

Even if you were returning a valid pointer, the fact that your function returns a void * means that any type information regarding what that pointer was pointing to is lost. 即使您返回一个有效的指针,您的函数返回void *的事实意味着有关该指针指向的内容的任何类型信息都将丢失。 You could print one or more bytes starting at that address, but it won't tell you what the original type was. 您可以从该地址开始打印一个或多个字节,但它不会告诉您原始类型是什么。

Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it. 即使该指针有效,您也无法获得足够的信息来强制转换为某些东西,然后将其打印出来。 No information of its size, no information of its internal layout. 没有关于其大小的信息,没有其内部布局的信息。 So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type. 所以,你根本无法打印void *指向的内容,除非你手边有一些手工准备的信息,并强制static_cast为已知类型。 For example: 例如:

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.

相关问题 如何确定运行时void *指针是指向Objective-C对象还是C ++对象 - How can I determine whether a void * pointer points to a objective-c object or a c++ object at runtime 如何获取指针指向的变量的类型? - How can I get the type of the variable a pointer points to? 我可以将void *指针分配给char *指针吗? - Can I assign void* pointer to char* pointer? 如何在C#中将void指针转换为struct - How I can convert void pointer to struct in C# 我如何在GoogleMock中检查作为无效指针传递的字符串参数 - How can I check a string parameter in googlemock that is passed as void pointer 在void getData()中,如何访问由void *指针限制的内存位置? - In void getData() , How can I access the memory location returmed by void* pointer? 可以将数据传递到void指针而不指向变量的指针 - Can you pass data into a void pointer without a pointer to a variable 如何声明带有void *指针的C ++原型,以便它可以采用任何指针类型? - How do I declare a C++ prototype with a void * pointer so that it can take any pointer type? 如何更改字符串指针指向的字符? - How can I change the character a string pointer points to? 如何判断指针是否指向派生类型的实例? - How can I tell whether a pointer points to an instance of a derived type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM