Jackie Wang
Jackie Wang

Reputation: 95

Issue with returning a char* which is a struct

I am new to C++, and I am trying to return the struct declared within a class via char*.

#include<iostream>
using namespace std;
#include <cstring>

class test
{
public:
    struct pair
    {
        int a,b;
    };
    test(){
        pir=new pair;
        pir->a=1;
        pir->b=2;
    }

    void readx(char* str)
    {
        char* str2=new char[sizeof(pair)+1];
        str2=reinterpret_cast<char*>(pir);
        strncpy(str,str2,sizeof(pair));
    }
private:
    pair* pir;

};

int main()
{
    test t;
    char* ptr;
    t.readx(ptr);
    cout<<*((int*)ptr)<<endl;
    cout<<*((int*)ptr+4)<<endl;
    return 0;
}

I have tried multiple ways but still failed to return a char* that can be reinterpreted into the struct. Actually the returned char* can only hold the first parameter, losing information about the second parameter, despite that I have used strncpy function. The output of this test code is

1
0 

How could I return the everything about struct within the class?

Upvotes: 0

Views: 65

Answers (3)

mpiatek
mpiatek

Reputation: 1343

You've got serious problems with your code. If it's really working, it's working only by accident.

  1. Whether it's strncpy or memset you use it doesn't matter too much because you are passing unitialized pointer to the functions which writes to it:

    char* ptr;
    t.readx(ptr);
    

    Where does ptr point to? It may point almost anywhere and using it as memcpy target is unpredictable. If you are not very unlucky, you will get a segfault/access violation.

  2. Your readx method does some crazy thing:

    char* str2 = new char[sizeof(pair)+1];
    str2 = reinterpret_cast<char*>(pir);
    

    Here you first alocate some storage and assign its address to str2 then you re-assign it to address of pir. You can never delete[] memory allocated by new[] so you introduce a memory leak.

  3. Constructor of class test allocates memory using new but you don't have corresponding destructor calling delete -> memory leak.

Then there is your ptr+4 problem which was already pointed by the others. Here you can find the code corrected to the point where you can expect it to do what you want.

#include <iostream>
#include <cstring>

using namespace std;

class test
{
public:
    struct pair
    {
        int a, b;
    };

    test() : pir{ new pair() }
    {
        pir->a = 1;
        pir->b = 2;
    }

    ~test() { delete pir; }

    void readx(char* str)
    {
        memcpy(str, reinterpret_cast<char*>(pir), sizeof(pair));
    }
private:
    pair* pir;
};

int main()
{
    test t;
    char* ptr = new char[sizeof(test::pair)];
    t.readx(ptr);

    cout << *((int*)ptr) << endl;
    cout << *((int*)ptr + 1) << endl;

    delete[] ptr;

    return 0;
}

When you understand the basic issues your code have read about the rule of five. For the test class you would add something like this:

#include <algorithm>

class test
{
    //...

    test(test const& other) : pir{ new pair() }
    {
        pir->a = other.pir->a;
        pir->b = other.pir->b;
    }

    test& operator=(test const& other)
    {
        test copy(other);
        swap(*this, copy);
        return *this;
    }

    test(test&& other) noexcept : pir{ nullptr }
    {
        swap(*this, other);
    }

    test& operator=(test&& other) noexcept
    {
        swap(*this, other);
        return *this;
    }

    friend void swap(test& lhs, test& rhs)
    {
        std::swap(lhs.pir, rhs.pir);
    }
};

Upvotes: 1

Mario Betancourt
Mario Betancourt

Reputation: 33

You are incrementing the int pointer by 4. This points 4 integers ahead. That's not what you want.

cout<<*((int*)ptr+1)<<endl;

That should get you b.

Upvotes: 0

zhm
zhm

Reputation: 3641

cout<<*((int*)ptr+4)<<endl;

This line should be:

cout<<*((int*)ptr+1)<<endl;

Because you have convert ptr to int *, which +1 means move pointer to next 4 bytes (size of int is 4).

Upvotes: 3

Related Questions