0
votes

Compréhension des indicateurs de C, d'incrémentation et de la déséroférience

On me donne un programme et je suis censé prédire sa sortie.

J'ai essayé de comprendre le programme étape par étape et d'écrire la valeur des variables à chaque point du programme, mais je ne suis pas sûr de ce que font ces opérations:

incrément ( &je); incrément (& a [i]);

Result: i = 1 
a[0] = 6
a[1] = 12

La solution est:

#include<stdio.h> 

void increment(int *ptr){
    ++ *ptr;
} 

int main(){ 
    int a[]={5,10},i=0; 
    increment(a); 
    increment(&i); 
    increment(&a[i]); 
    increment(a+i);
    printf("\nResult:i=%d\n",i); 
    printf("a[0]=%d\n a[1]= %d\n", a[0], a[1]);
    return 0 ;
}

Pourriez-vous m'aider comprendre comment je peux trouver la solution? Merci!

c

5 commentaires

De quelle étape exacte n'êtes-vous pas sûr? Comprenez-vous ce que fait l'adresse de l'opérateur & ?


++ * ptr; est identique à * ptr + = 1;


& a [i] est identique à a + i est à la valeur identique à a .


Merci pour toutes vos explications! Une chose dont je ne suis toujours pas sûr est ce qui se passe après incrément (a) . J'ai pensé que son incrémenterait un pour qu'il pointe vers un [1], mais apparemment ce n'est pas le cas?


@ user8558648 la fonction increment () prend un pointeur et incrémente la valeur pointée. increment (a) incrémente la valeur stockée à a [0] . Vérifiez ma réponse pour une explication étape par étape


4 Réponses :


0
votes

Mais je ne suis pas sûr de ce que font ces opérations:

incrément (& I); transmet l'adresse de i variable à votre fonction d'incrément. Cette fonction ne conçoit pas le pointeur et incrémente la valeur pointue à une valeur, qui est essentiellement équivalente à i ++ .

incrément (& a [i]) fait la même chose, mais il passe maintenant l'adresse de l'élément i -th de A . Étant donné que i a été incrémenté à 1 avant, il est équivalent à A [1] ++ . .


0 commentaires

0
votes

La fonction increment (int * ptr) attend un pointeur vers un int , c'est-à-dire une adresse.

La variable i étant de type int , vous devez passer son adresse en utilisant l'opérateur address-of & < / code> comme dans: increment(&i)

a [i] est égal à * (a + i) - c'est-à-dire que vous accédez à l'adresse de l'élément du tableau à a + i et le déréférencer afin d'obtenir la valeur de cet élément du tableau à la position i .
Même raison que dans le premier cas, increment attend un pointeur et il faut donc passer une adresse comme dans: increment(&a[i[ ));


0 commentaires

0
votes

OK, voici une explication étape par étape dans les commentaires intégrés. J'espère que cela aide. Vous devrez peut-être faire défiler horizontalement pour lire le commentaire complet.

#include<stdio.h> 
// This function takes a pointer to int and increments the pointed value
void increment(int *ptr){++ *ptr;}      

int main(){ 
    int a[]={5,10},i=0; // It doesn't look so but here, a is a pointer to int
    increment(a);       // increments the first value pointed by a (a[0]) so now a is [6,10]
    increment(&i);      // increments i, now i = 1
    increment(&a[i]);   // increments a[1], now a = [6,11]
    increment(a+i);     // since i = 1, increments the value right after the one pointed by a so again, a[1], now a = [6,12]
    printf("\nResult:i=%d\n",i);        
    printf("a[0]=%d\n" "a[1]= %d\n");
    return 0 ;
}


4 commentaires

Cela n'a pas l'air mais ici, a est un pointeur vers int . Non, a n'est pas un pointeur. a est un tableau d'entiers. Le tableau n'est pas un pointeur. Le tableau et le pointeur sont différents.


Oui @HS, les tableaux déclarés comme ceci int a [] ont un comportement légèrement différent des pointeurs car ils sont alloués statiquement mais en fait, ce sont vraiment des pointeurs dans le sens où la valeur que contient a est une adresse en mémoire. Et a [0] équivaut à * a . Vérifiez cet extrait de code: gcc.godbolt.org/z/SGCJ1z


@ Ki Jéy a [0] équivaut à * a ne signifie pas que le tableau a est un pointeur.


la variable a contient une adresse. Vous pouvez lire la valeur stockée dans cette adresse en la déréférençant avec * . * a contient l'entier souhaité. Appelez ça comme vous voulez. Pour moi, c'est un indicateur.



1
votes

Commençons par quelques informations générales.

Tout d'abord, l'expression ++ i s'évalue à la valeur actuelle de i plus 1 - comme un côté effet , la valeur stockée dans i est incrémentée. En tant qu'expression autonome, elle équivaut à peu près à i = i + 1 .

Deuxièmement, sauf s'il s'agit de l'opérande des opérateurs sizeof ou unaire & , une expression de type "N -element tableau de T "( T [N] ) sera converti (" decay ") en une expression de type" pointeur vers T "( T * ), et la valeur de l'expression sera l'adresse du premier élément du tableau.

Enfin, l'expression a [i] est définie comme * (a + i) - avec une adresse de départ a , décalez i éléments (et non octets!) à partir de cette adresse et déréférencer le résultat. Cela signifie que l'expression a + i est équivalente à l'expression & a [i] .

Voyons comment cela s'applique à votre code:

Dans la fonction incrémentation , la ligne

 ptr == &i
*ptr ==  i

ajoute 1 à l'élément vers lequel pointe ptr .

Lorsque vous appelez increment (a) , l ' expression a a le type "Tableau à 2 éléments de int ". Étant donné que a n'est pas l'opérande des opérateurs sizeof ou unaire & , cette expression "décroît" en type "le pointeur vers int "( int * ), et la valeur de l'expression est l'adresse du premier élément de a . IOW, c'est exactement la même chose que si vous aviez écrit incrément (& a [0]) . Par conséquent, dans la fonction incrémentation , ce qui suit est vrai:

 ptr == &a[0]
*ptr ==  a[0]

Ainsi, l'expression ++ * ptr est équivalent à l'expression ++ a [0] . Après cet appel, a [0] vaut maintenant 6.

Lorsque vous appelez increment (& i) , ptr maintenant pointe vers i:

++ *ptr;

donc ++ * ptr équivaut à l'expression ++ i , vous ajoutez donc 1 à i .

Lorsque vous appelez increment (a [i]) , i est égal à 1, donc cela équivaut à appeler increment (a [1]) . Après cet appel, a [1] est égal à 11.

Et enfin, incrément (a + i) équivaut à incrément (& a [i]) , ce qui équivaut à incrément (& a [1]) , et après cet appel, a [1] est égal à 12.


0 commentaires