Изменить содержимое памяти адреса возврата функции - PullRequest
0 голосов
/ 25 января 2019

Можно ли изменить содержимое адреса памяти возвращаемого значения функции? функции возвращают значение локальной переменной.

В следующем примере, скомпилированном для моей машины (x86-64) без предупреждений:

#include <stdio.h>

int get_val1()
{
  int ret = 1;
  return ret;
}

int get_val2()
{
  int ret = 2;
  return ret;
}

int get_val3()
{
  int ret = 3;
  return ret;
}

void redefine_ints(int *val1, int *val2, int *val3) {
  *val1 = 10;
  *val2 = 11;
  *val3 = 12;
}

void print_and_redefine_ints(int val1, int val2, int val3) {
  printf("val1 %d val2 %d val3 %d\n", val1, val2, val3);
  redefine_ints(&val1, &val2, &val3);
  printf("rval1 %d rval2 %d rval3 %d\n", val1, val2, val3);
}

int main()
{
  print_and_redefine_ints(get_val1(), get_val2(), get_val3());
  return 0;
}

Я получаю следующий вывод:

val1 1 val2 2 val3 3
rval1 10 rval2 11 rval3 12

Это ожидаемый результат, но как это возможно? Где хранятся эти переменные?

Ответы [ 3 ]

0 голосов
/ 25 января 2019

Можно ли изменить содержимое адреса памяти возврата (значения) функции?

Нет, это не так.

Однако, это не так здесь . В вашем коде возвращаемые значения вызовов функций get_val<n>() сохраняются в параметрах функций int val1, int val2, int val3. Они локальны для вызываемой функции. Время жизни этих переменных - период выполнения функции.

Цитата C11, глава §6.2.1,

[...] Если декларатор или спецификатор типа объявляет, что идентификатор появляется внутри блока или в списке объявлений параметров в определение функции, идентификатор имеет область видимости блока, которая заканчивается в конце связанный блок. [....]

и, из §6.9.1, Определение функции,

Каждый параметр имеет длительность автоматического хранения; его идентификатор lvalue

Таким образом, как и любая другая локальная переменная, вы можете изменять содержимое этих переменных, используя их адрес.

0 голосов
/ 25 января 2019

Ничья может объяснить больше, чем какой-либо текст.Я буду использовать только 1 get_val1() в этом примере.

print_and_redefine_ints(get_val1());
                           |
                           |
                         [CALL]
                           |
                           |
                           V
                    int get_val1()
                    {
                        int ret = 1;<----------------------------------------------------+
                        return ret;                                                      |
                    }      |                                                             |
                           |                                                             |
                    [COPY OF VALUE]                                                      |
                           |                                                             |
                           |                                                             |
                           +---+                                                         |
                               |                                                         |
                               |                                                         |
                               V                                                         |
void print_and_redefine_ints(int val1) {                                                 |
    printf("val1 %d\n");        ^                                                        |
    redefine_ints(&val1);       |                                                        |
                    |           +--------------------------------------------+           |
                    |                                                        |           |
          [POINTER AKA REFERENCE]                                            |           |
                    |                                                        |           |
                     |                                                       |           |
                      V                                                      |           |
void redefine_ints(int *val1) {                                              |           |
    *val1 = 10; //<---- the value is changed, then its referenced value (this one, NOT THIS ONE) is changed too
}                     |
                      |
                      +---+
                          |
                    [VALUE CHANGED]
                          |
                          |
                          V
    printf("rval1 %d\n", val1);
    printf("original val1 %d\n", get_val1()); //if you add this line, you'll notice the returned value of get_val1() is still 1
}
0 голосов
/ 25 января 2019

Да, это четко определено C.

Анонимные временные int, созданные get_val...(), имеют время жизни вместе со всем оператором, в котором они созданы.

Но учтите, что вы берете копию значения каждого из этих int s при вызове print_and_redefine_ints, поэтому здесь ничего особенного не происходит.

(Обратите внимание, что вы не сможете привязывать указатели к анонимным временным int с int* параметрам функции.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...