私は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
と++
の間に違いはありますか?両方とも同じだと思いました。
違いは演算子の優先順位によるものです。
ポストインクリメント演算子++
は、参照解除演算子*
よりも優先順位が高くなります。したがって、*ptr++
は*(ptr++)
と同等です。言い換えれば、ポストインクリメントはポインタを修正するものであり、ポインタが指すものではありません。
代入演算子+=
は、参照解除演算子*
よりも優先順位が低いため、*ptr+=1
は(*ptr)+=1
と同等です。つまり、代入演算子は、ポインターが指す値を変更し、ポインター自体を変更しません。
操作の順序 を示すために括弧を適用してみましょう
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
配列にコピーするために使用される一般的な方法です。
とてもいい質問です。
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.
* ptr + = 1:ptrが指す増分データ。 * ptr ++:ポインターが指すデータではなく、次のメモリー位置を指すポインターを増分します。