Link to home
Start Free TrialLog in
Avatar of chsalvia
chsalvia

asked on

Returning a struct

Suppose you have a function that returns a struct, but doesn't take a struct as a parameter.  Is there a way to return all the struct values?

Something like:

typedef struct {
   char* word;
   int len;
}thing;

thing& func1(char* str)
{
   return { str, strlen(str); }  
}

The above code doesn't work, of course, but hopefully it shows what I'm trying to do.  func1 is a function of type thing, which is a struct - how can I return both values of struct from the function, and it is correct to pass a struct as a reference?
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of leisner
leisner

AlexFM,

In this example:
thing func1(char* str)
{
    thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}
do you mean can or can't?   thing is on the stack, so it goes away when the
function goes out of scope -- which is a bug.

If you want to return multiple elements, you create temporary structures, or pass by reference....

Another way is for the caller to allocate the structure, pass down a pointer to it, and maybe the
calling function return status?

For example:

bool func1(thing *pthing, char *string)
{
    if(NULL == pthing || NULL == string)
        return false;
   pthing->word = strdup(string); // do you want the string or a copy to it?
   pthing->len = strlen(string) + 1; // add the NULL terminate?
   return true;
}

If you want  the return value to be the structure, you can use static instead of auto inside the
function -- but only one copy of the data is valid at one time.

My first sample is OK, it doesn't return reference. It returns structure by value - this means, caller gets temporary structure instance which is assigned to it's variable:

thing t;
t = func1("bla");
Yep, AlexPM, you're right.

But one caveat of that style of function calls -- you make an extra copy of the structure.
In this case the cost is minimal, but if you start  call to func1 repeatedly and thing is large, it gets expensive....

>> But one caveat of that style of function calls -- you make an extra copy of the structure.
In that case don't return it. Do something like this

void func1(char* str, thing& t)
{
    t.word = str;
    t.len = strlen(str);
    return s;
}
I've had lots of problems with this particular style of programming

thing func1(char* str)
{
    thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}

especially in a multi-tasking environment.  I've seen it in a few books and some people swear by it but I wouldn't recommend returning anything other than a basic type or a pointer.  I've had no end of crashes when there are shallow copies and destructors delete pointers to arrays.  If you must use this style, do it this way

thing func1(char* str)
{
    static thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}

That way, you know the stack will not be wiped and no destructor will be called.  The only problem is that the result must be stored straight away and it is not thread safe.
>>>> thing& func1(char* str) {  return { str, strlen(str); }   }

You could do the following:

thing& func(char* str)
{
     static thing s = { 0 };   // init
     thing t  = { str, strlen(str) };
     return s = t;
}

Here you return the static variable by reference (what isn't thread-safe as cup already told).

>>>> return s = t;

That invokes the (automatically generated) copy constructor of struct thing. However, it doesn't work in C but only in C++ cause there is no copy constructor in C. To make that clear I would change the definition of the struct to

struct thing
{
     char* psz;
     int     len;
};

BTW, I would not use the name 'word' for a string variable cause 'word' means a 16-bit integer.

Regards, Alex


>>>> That invokes the (automatically generated) copy constructor of struct thing.

It is the assignment operator that is invoked, *not* the copy constructor.
>>>> but if you start  call to func1 repeatedly and thing is large, it gets expensive....

Repeatedly means "millions of repetitions" before you actually could measure a difference.  The "expensive" argument came from times of 16-bit code where the stack was limited to some k bytes. If 'thing' is a structure where you have a few instances only, it doesn't matter - regarding effiency - whether it is passed by reference or by value. Actually, all modern container classes store by value (means they make copies from elements that were passed by value).

Regards, Alex

>>>> Accept: AlexFM {http:#16293571}

Yes, that's a good decision.

Regards