web-dev-qa-db-ja.com

Cの* ptr + = 1と* ptr ++の違い

私はCの勉強を始めたばかりで、ポインターを関数のパラメーターとして渡すことについて1つの例を実行すると、問題が見つかりました。

これは私のサンプルコードです:

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

*ptr+=1*ptr++に変更すると、16行目で問題が発生します。予想される結果は配列全体と番号1である必要がありますが、*ptr++を使用すると結果は0になります。

+=1++の間に違いはありますか?両方とも同じだと思いました。

121
huy nguyen

違いは演算子の優先順位によるものです。

ポストインクリメント演算子++は、参照解除演算子*よりも優先順位が高くなります。したがって、*ptr++*(ptr++)と同等です。言い換えれば、ポストインクリメントはポインタを修正するものであり、ポインタが指すものではありません。

代入演算子+=は、参照解除演算子*よりも優先順位が低いため、*ptr+=1(*ptr)+=1と同等です。つまり、代入演算子は、ポインターが指す値を変更し、ポインター自体を変更しません。

285
user3386109

操作の順序 を示すために括弧を適用してみましょう

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

もう一度やりましょう

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

そして再び

*ptr++
*(ptr++)
  • *ptr += 1では、ポインターpointsへの変数の値をインクリメントします。
  • *ptr++では、ステートメント全体(コード行)が完了した後、ポインターをインクリメントafterし、変数ourポインターへの参照を返しますポイントへ。

後者では、次のようなことができます。

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++);
}

これは、src配列を別のdest配列にコピーするために使用される一般的な方法です。

7
Mateen Ulhaq

とてもいい質問です。

K&R「Cプログラミング言語」「5.1ポインターとアドレス」では、これに対する答えを得ることができます。

「単項演算子*および&は、算術演算子よりも厳密にバインドします」

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

「*や++のような単項演算子は右から左に関連付けられます。」

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

// *(ptr ++)のように機能します。

正しい方法は次のとおりです。

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

* ptr + = 1:ptrが指す増分データ。 * ptr ++:ポインターが指すデータではなく、次のメモリー位置を指すポインターを増分します。

2
user5787482