6
votes

Modifier le contenu de l'adresse mémoire du retour d'une fonction

Est-il possible de modifier le contenu de l'adresse mémoire de la valeur de retour d'une fonction? Les fonctions renvoient la valeur d'une variable définie localement.

Dans l'exemple suivant, compilé pour ma machine (x86-64) sans avertissements:

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

J'obtiens la sortie suivante :

#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;
}

C'est la sortie attendue, mais comment est-ce possible? Où sont stockées ces variables?


6 commentaires

redefine_ints (& val1, & val2, & val3); ici vous passez des références aux variables, c'est le seul point où elles sont modifiées.


Vous ne modifiez pas directement la valeur de retour d'une fonction. print_and_redefine_ints (get_val1 (), get_val2 (), get_val3 ()); Ici, vous passez les valeurs de retour à une autre fonction par valeur.


Je vais reformuler la question. Donnez-moi quelques minutes pour le modifier.


Vous ne modifiez rien de ce qui se trouve dans get_val1 () / 2/3. Mais, dans print_and_redefine_ints (int val1, int val2, int val3) {...} vous copiez les valeurs de retour des fonctions (car vous appelez de cette façon: print_and_redefine_ints (get_val1 (), get_val2 (), get_val3 ()); ) J'espère que cela aide


Le titre de la question et la première phrase de la question n'ont pas beaucoup de sens


@Jabberwocky: En effet; il n'est pas possible de construire ce que l'op vraiment veut demander dans le standard C.


3 Réponses :


5
votes

Oui, c'est un C. bien défini

Les temporaires anonymes int créés par get_val ... () ont une durée de vie contemporaine de la totalité de l'instruction dans laquelle ils sont créés .

Mais notez que vous prenez une copie de valeur de chacun de ces int lorsque vous appelez print_and_redefine_ints donc il n'y a rien de particulièrement spécial ici.

(Notez que vous ne pourrez pas lier les pointeurs aux paramètres de fonction int temporaires anonymes aux paramètres de fonction int * .) < / p>


0 commentaires

3
votes

Est-il possible de modifier le contenu de l'adresse mémoire du retour (valeur) d'une fonction?

Non, ce n'est pas le cas.

Cependant, ce n'est pas le cas ici . Dans votre code, les valeurs de retour des appels de fonction get_val () sont stockées dans les paramètres de fonction int val1 , int val2 , < code> int val3 . Ils sont locaux à la fonction appelée. La durée de vie de ces variables correspond à la période d'exécution de la fonction.

Citant C11 , chapitre §6.2.1,

[...] Si le déclarateur ou le spécificateur de type déclare que l'identifiant apparaît à l'intérieur d'un bloc ou dans la liste des déclarations de paramètres dans une définition de fonction, l'identifiant a une portée de bloc, qui se termine à la fin du bloc associé. [....]

et, à partir du §6.9.1, Définition de fonction,

Chaque paramètre a une durée de stockage automatique; son identifiant est une lvalue

Ainsi, comme toute autre variable locale, vous pouvez modifier le contenu de ces variables en utilisant leur adresse.


0 commentaires

5
votes

Un tirage au sort peut expliquer plus que du texte. Je n'utiliserai qu'un seul get_val1 () dans cet exemple.

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
}


1 commentaires

Il est considéré comme impoli pas de voter pour une réponse avec l'art ASCII.