121 votes

Différence entre *ptr += 1 et *ptr++ en C

Je viens de commencer à étudier le C, et en faisant un exemple de passage de pointeur à pointeur comme paramètre de fonction, j'ai trouvé un problème.

Voici mon exemple de code :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int* allocateIntArray(int* ptr, int size){
    if (ptr != NULL){
        for (int i = 0; i < size; i++){
            ptr[i] = i;
        }
    }
    return ptr;
}

void increasePointer(int** ptr){
    if (ptr != NULL){
        *ptr += 1; /* <----------------------------- This is line 16 */
    }
}

int main()
{
    int* p1 = (int*)malloc(sizeof(int)* 10);
    allocateIntArray(p1, 10);

    for (int i = 0; i < 10; i++){
        printf("%d\n", p1[i]);
    }

    increasePointer(&p1);
    printf("%d\n", *p1);
    p1--;
    free(p1);
    fgets(string, sizeof(string), stdin);
    return 0;
}

Le problème se produit à la ligne 16, lorsque je modifie *ptr+=1 a *ptr++ . Le résultat attendu devrait être le tableau entier et le numéro 1, mais lorsque j'utilise la fonction *ptr++ le résultat est 0.

Y a-t-il une différence entre +=1 y ++ ? Je pensais que les deux étaient identiques.

286voto

user3386109 Points 7228

La différence est due à la préséance des opérateurs.

L'opérateur de post-incrémentation ++ a une priorité plus élevée que l'opérateur de déréférencement * . Donc *ptr++ est équivalent à *(ptr++) . En d'autres termes, l'incrément de poste modifie le pointeur, pas ce vers quoi il pointe.

L'opérateur d'affectation += a une précédence inférieure à celle de l'opérateur de déréférencement * donc *ptr+=1 est équivalent à (*ptr)+=1 . En d'autres termes, l'opérateur d'affectation modifie la valeur vers laquelle pointe le pointeur, et ne modifie pas le pointeur lui-même.

21voto

Younes Regaieg Points 1962

L'ordre de préséance des 3 opérateurs concernés par votre question est le suivant :

post-incrément ++ > déréférencement * > affectation +=

Vous pouvez vérifier ceci page pour plus de détails sur le sujet.

Lors de l'analyse d'une expression, un opérateur qui est listé sur une certaine ligne sera lié plus étroitement (comme par des parenthèses) à ses arguments que tout opérateur qui est listé sur une ligne plus bas. Par exemple, l'expression *p++ est interprété comme *(p++) et non comme (*p)++ .

Pour faire court, afin d'exprimer cette mission *ptr+=1 en utilisant l'opérateur de post-incrémentation, vous devez ajouter des parenthèses à l'opérateur de déréférence pour donner à cette opération la priorité sur ++ comme dans ce *`(ptr)++`**

7voto

muntoo Points 4905

Appliquons des parenthèses pour montrer le ordre des opérations

a + b / c
a + (b/c)

Recommençons avec

*ptr   += 1
(*ptr) += 1

Et encore avec

*ptr++
*(ptr++)
  • Sur *ptr += 1 nous incrémentons la valeur de la variable notre pointeur points à.
  • Sur *ptr++ nous incrémentons le pointeur après notre déclaration entière (ligne de code) est faite, et nous retournons une référence à la variable notre pointeur points à.

Ce dernier vous permet de faire des choses comme :

for(int i = 0; i < length; i++)
{
    // Copy value from *src and store it in *dest
    *dest++ = *src++;

    // Keep in mind that the above is equivalent to
    *(dest++) = *(src++);
}

Il s'agit d'une méthode courante utilisée pour copier un src dans un autre tableau dest le tableau.

3voto

Nick.Sang Points 21

Très bonne question.

Dans le document K&R "C programming language" "5.1 Pointers and Addresses", nous pouvons obtenir une réponse à cette question.

"Les opérateurs unaires * et & se lient plus étroitement que les opérateurs arithmétiques"

*ptr += 1      //Increment what ptr points to.

"Les opérateurs unaires comme * et ++ s'associent de droite à gauche ."

*ptr++        //Increment prt instead of what ptr point to.

//Il fonctionne comme *(ptr++).

Le bon chemin est :

(*ptr)++      //This will work.

2voto

user5787482 Points 11

*ptr += 1 : Incrémente les données vers lesquelles ptr pointe. *ptr++ : Incrémente le pointeur qui pointe vers l'emplacement mémoire suivant au lieu de la donnée vers laquelle pointe le pointeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X