2013-07-27 3 views
4

Я прочитал о return значения между вызовами функции,
и экспериментировал с в следующем фрагменте кода:Какова продолжительность возвращаемого значения функции?

/* 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; 
} 

код компилируется без ошибок и предупреждений.
Протестировано с помощью GCC 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) и Компиляторы Visual C++.

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

Выход:
Доброе утро!

Я немного смущен результатом.
Код написан правильно?

Мой вопрос:

  • Что видимость return значения функции (массив из struct в приведенном выше примере), и как правильно обращаться к ним?

  • Где заканчивается срок службы значения return?

+0

Возвращаемое значение является временным. Он отбрасывается после его использования. Если вы не храните его в переменной, она исчезнет после того, как вы впервые ссылаетесь на нее. –

+0

@JoachimPileborg Да, я получил его, а затем удалил свой комментарий перед вашим комментарием. :) –

+0

@boleto Почему вы смущены? Вы ожидали чего-то еще? – Xaqq

ответ

5

В C, время жизни временной в вашем примере заканчивается, когда выражение printf закончено:

  • Per C 2011 (N1570) 6.2.4 8, время жизни временных концов, когда оценка полное выражение (или декларатор), содержащее его, заканчивается: «Не-lvalue выражение со структурой или типом объединения, где структура или объединение содержит член с типом массива (включая рекурсивно, члены всех содержащихся структур и объединений) относится к объект с автоматическим временем хранения и временным временем жизни.36). Его время жизни начинается, когда выражение оценивается, а его начальное значение является значением выражения. Его время жизни заканчивается, когда заканчивается оценка содержащего полное выражение или полного декларатора ».
  • Per 6.8 4:« Полное выражение - это выражение, которое не является частью другого выражения или декларатора ». Per 6.7.6 3: «Полный декларатор - это декларатор, который не является частью другого декларатора».
  • Следовательно, время жизни временного в вашем примере заканчивается, когда выражение printf закончено.

В C++, время жизни в вашем примере такой же, как и в C:

  • Per C++ 2010 (N3092) 12,2 3: «Временные объекты уничтожаются на последнем этапе оценки полнодиапазонными выражение (1.9), которое (лексически) содержит точку, в которой они были созданы. "
  • Per 12.2 4 и 5: «Существует два контекста, в которых временные объекты уничтожаются в другой точке, чем конец полного выражения. Первый контекст - это когда конструктор по умолчанию вызывается для инициализации элемента массива. Если конструктор имеет один или несколько аргументов по умолчанию, уничтожение каждого временного объекта, созданного в выражении аргумента по умолчанию, секвенируется перед построением следующего элемента массива, если оно есть. »« Второй контекст - это когда ссылка привязана к временному. Временное, к которому привязана ссылка, или временное, являющееся полным объектом подобъекта, к которому привязана ссылка, сохраняется для срока службы ссылки, за исключением: ... "(я сократил исключения для краткости, поскольку они не применяются здесь.)
  • Итак, ваш пример тот же, что и в C++, временный объект уничтожается как последний шаг при оценке выражения printf.
+0

То, что я всегда видел, это то, что возвращаемый объект будет длиться не далее, чем следующая точка последовательности, вызванная вызовом 'printf'. Разве нет оценки выражения до вызова функции? – Sebivor

+0

@EricPostpischil, Хорошее объяснение! только один маленький вопрос - возможно ли изменить данные массива * при вызове функции 'printf()'? – boleto

+0

@boleto Если вы спрашиваете, существуют ли спецификаторы формата printf, вызывающие объект, на который указывает соответствующий аргумент, чтобы существовать, существуют. Однако возвращаемое значение функции не является изменяемым значением lvalue, поэтому любая попытка записи на него будет неопределенным поведением. – Sebivor

2

Функции xprint возвращает копию структуры, и компилятор хранит эту копию во временном, и время жизни является временными конструкциями длительности вызова в printf функции. Когда функция printf возвращает, этот временный объект уничтожается.

+0

нет, но этот код даст ошибку сегментации. –

Смежные вопросы