We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Returning a struct

chsalvia
chsalvia asked
on
Medium Priority
466 Views
Last Modified: 2013-12-14
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?
Comment
Watch Question

Commented:
You can return local variable by value:

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

You can return pointer to allocated structure, client is responsible to release it:

thing* func1(char* str)
{
    thing* p = new thing();
    p->word = str;
    p->len = strlen(str);
    return p;
}

You cannot return reference to local variable which is destroyed when function exits. You can retun reference to global variable or class member, bt I don't think that this is what you want.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Commented:
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.

Commented:
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");

Commented:
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;
}
cup

Commented:
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
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.