web-dev-qa-db-fra.com

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

Je viens juste de commencer à étudier le langage C et, lorsqu’on a donné un exemple concernant le passage d’un point à l’autre en tant que paramètre d’une fonction, j’ai trouvé un problème.

Ceci est 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 à *ptr++. Le résultat attendu devrait être l'ensemble du tableau et le nombre 1, mais lorsque j'utilise *ptr++ le résultat est 0.

Existe-t-il une différence entre +=1 et ++? Je pensais que les deux sont les mêmes.

121
huy nguyen

La différence est due à la priorité de l'opérateur.

L'opérateur post-incrémentation ++ A une priorité supérieure à celle de l'opérateur de déréférence *. Donc *ptr++ Est équivalent à *(ptr++). En d'autres termes, l'incrément de publication modifie le pointeur, et non ce qu'il pointe.

L'opérateur d'assignation += A une priorité inférieure à celle de l'opérateur de déréférence *, De sorte que *ptr+=1 Équivaut à (*ptr)+=1. En d'autres termes, l'opérateur d'affectation modifie la valeur indiquée par le pointeur et ne modifie pas le pointeur lui-même.

285
user3386109

L'ordre de priorité des 3 opérateurs impliqués dans votre question est le suivant:

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

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

Lors de l'analyse syntaxique d'une expression, un opérateur répertorié sur une ligne sera lié plus étroitement (comme entre parenthèses) à ses arguments que tout opérateur répertorié sur une ligne située plus bas. Par exemple, l'expression *p++ Est analysée comme *(p++), et non comme (*p)++.

En résumé, pour exprimer cette affectation *ptr+=1 À l'aide de l'opérateur post-incrémentation, vous devez ajouter des parenthèses à l'opérateur de déréférencement afin de donner à cette opération la priorité sur ++, Comme dans ceci (*ptr)++

21
Younes Regaieg

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

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

Faisons-le encore avec

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

Et encore avec

*ptr++
*(ptr++)
  • Dans *ptr += 1, nous incrémentons la valeur de la variable notre pointeur pointe sur.
  • Dans *ptr++, nous incrémentons le pointeur après la totalité de notre instruction (ligne de code) est terminée et renvoyons 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 tableau src dans un autre tableau dest.

7
Mateen Ulhaq

Très bonne question.

Dans le langage de programmation "C" de K & R, "5.1 Pointeurs et adresses", 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 ++ associent de droite à gauche."

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

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

La manière correcte est:

(*ptr)++      //This will work.
3
Nick.Sang

* ptr + = 1: incrémente les données vers lesquelles pointe ptr. * ptr ++: Pointeur d'incrémentation qui pointe vers l'emplacement de mémoire suivant au lieu des données pointées par ce pointeur.

2
user5787482