7

I read about the return values between function calls,
and experimented with the following code snippet :

/* file structaddr.c */
#include <stdio.h>    
#define MSIZE 10

struct simple
{   
    char c_str[MSIZE];
};
struct simple xprint(void)
{
    struct simple ret = { "Morning !" };
    return ret;
}
int main(void)
{   
    printf("Good %s\n", xprint().c_str);    
    return 0;
}

The code is compiled without errors and warnings .
Tested with GCC 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) and Visual C++ compilers .

 gcc -m32 -std=c99 -Wall -o test  structaddr.c  
 cl -W3 -Zi -GS -TC -Fetest structaddr.c

Output :
Good Morning !

I'm a little confused by the result .
The code is written correctly ?

My Question :

  • What is the visibility of the function return value( array from a struct in above example ), and how to properly access them ?

  • Where ends lifetime of a return value ?

boleto
  • 1,149
  • 1
  • 22
  • 32
  • The return value is a temporary. It's discarded after it's used. If you don't store it into a variable, it's gone after you reference it for the first time. –  Jul 27 '13 at 20:20
  • @JoachimPileborg yes I got it just then deleted my comment before your this comment. :) – Grijesh Chauhan Jul 27 '13 at 20:28
  • @boleto Why are you confused? Did you expect something else? – Xaqq Jul 27 '13 at 20:35
  • C and C++ are different languages, and you should either specify just one of them in a question or enter two questions, one for each language, unless there is reason to believe the answer is essentially the same in both languages. – Eric Postpischil Jul 27 '13 at 23:15

2 Answers2

9

In C, the lifetime of the temporary in your example ends when the printf expression is finished:

  • Per C 2011 (N1570) 6.2.4 8, the lifetime of a temporary ends when the evaluation of the full expression (or declarator) containing it ends: “A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime. Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression or full declarator ends.”
  • Per 6.8 4: “A full expression is an expression that is not part of another expression or of a declarator.” Per 6.7.6 3: “A full declarator is a declarator that is not part of another declarator.”
  • Therefore, the lifetime of the temporary in your example ends when the printf expression is finished.

In C++, the lifetime in your example is the same as in C:

  • Per C++ 2010 (N3092) 12.2 3: “Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.”
  • Per 12.2 4 and 5: “There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array. If the constructor has one or more default arguments, the destruction of every temporary created in a default argument expression is sequenced before the construction of the next array element, if any.” “The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:…” (I have omitted the exceptions for brevity, as they do not apply here.)
  • So your example is the same in C++, the temporary object is destroyed as the last step in evaluating the printf expression.
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • The way I've always seen it is that the returned object will last no longer than the next sequence point, which is caused by the call to `printf`. Isn't there an evaluation of the expression prior to the function call? – autistic Jul 28 '13 at 00:02
  • @EricPostpischil, Good explanation ! just one small question - Is it possible to modify *array data*, when calling the `printf()` function? – boleto Jul 28 '13 at 01:11
  • @boleto If you're asking whether or not printf format specifiers that cause the object pointed to by the corresponding argument to be written to exist, there are. However, the return value of a function isn't a modifiable lvalue, and so any attempt to write to it would be undefined behaviour. – autistic Jul 28 '13 at 01:46
  • @undefinedbehaviour: The expression returned by `xprint` cannot be evaluated before calling `xprint`, still it does not exist until `xprint` returns it. It must be evaluated before `printf` is called but, in the C abstract model, it continues to exist until the `printf` expression is completed. Sequence points are irrelevant to that lifetime, because the C standard’s rule about when the lifetime ends does not mention sequence points. – Eric Postpischil Jul 28 '13 at 01:49
  • @boleto: You will have to explain what you mean in more detail. – Eric Postpischil Jul 28 '13 at 01:51
  • @EricPostpischil this code [access illegal memory](http://ideone.com/2H3FZk), This code terminated by `SIGSEGV` signal that is due to access right violation at legal memory-runtime-error – Grijesh Chauhan Jul 28 '13 at 05:38
  • @GrijeshChauhan: What makes you think that is a bug in the program rather than a bug in the C compiler that `ideone` is using? At the command line, using GCC, try compiling it with `-stdc=99` rather than GCC default variant of C (which is not standard C). If I change the language at `ideone` to `C99 strict`, the program works. – Eric Postpischil Jul 28 '13 at 10:20
  • 1
    @GrijeshChauhan: Note that the default for GCC is `-std=gnu89`. So you are testing the program using a non-standard variant of the C language that is nearly a quarter of a century old. – Eric Postpischil Jul 28 '13 at 10:29
2

The function xprint returns a copy of the structure, and the compiler stores this copy in a temporary, and the temporaries lifetime is the duration of the printf function call. When the printf function returns, that temporary object is destroyed.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621