簡體   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