logo

C でのポインター演算

ポインタに対して加算や減算などの算術演算を実行できます。ただし、ポインタにはアドレスが含まれていることがわかっているため、他のオペランドが整数型の場合、ポインタに対して実行された算術演算の結果もポインタになります。ポインタからポインタの減算では、結果は整数値になります。 C言語ではポインタに対して以下の算術演算が可能です。

  • インクリメント
  • デクリメント
  • 追加
  • 引き算
  • 比較

C でのポインターのインクリメント

ポインタを 1 ずつインクリメントすると、ポインタはすぐ次の位置を指し始めます。ポインタの値は、ポインタが指しているデータ型のサイズだけ増加するため、これは一般的な算術とは多少異なります。

ポインターのインクリメント操作を使用して配列を走査することができます。ポインターは配列のすべての要素を指し続け、その要素に対して何らかの操作を実行し、ループ内で自身を更新します。

ポインタをインクリメントするルールを以下に示します。

 new_address= current_address + i * size_of(data type) 

ここで、 i はポインタが増加する数です。

32ビット

32 ビット int 変数の場合、2 バイトずつ増加します。

64ビット

64 ビット int 変数の場合、4 バイトずつ増加します。

64 ビット アーキテクチャでポインタ変数をインクリメントする例を見てみましょう。

 #include int main(){ int number=50; int *p;//pointer to int p=&number;//stores the address of number variable printf('Address of p variable is %u 
',p); p=p+1; printf('After increment: Address of p variable is %u 
',p); // in our case, p will get incremented by 4 bytes. return 0; } 

出力

 Address of p variable is 3214864300 After increment: Address of p variable is 3214864304 

ポインタを使用した配列の走査

 #include void main () { int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; int i; printf('printing array elements...
&apos;); for(i = 0; i<5; i++) { printf('%d ',*(p+i)); } < pre> <p> <strong>Output</strong> </p> <pre> printing array elements... 1 2 3 4 5 </pre> <h2>Decrementing Pointer in C</h2> <p>Like increment, we can decrement a pointer variable. If we decrement a pointer, it will start pointing to the previous location. The formula of decrementing the pointer is given below:</p> <pre> new_address= current_address - i * size_of(data type) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will be decremented by 2 bytes.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will be decremented by 4 bytes.</p> <p>Let&apos;s see the example of decrementing pointer variable on 64-bit OS.</p> <pre> #include void main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-1; printf(&apos;After decrement: Address of p variable is %u 
&apos;,p); // P will now point to the immidiate previous location. } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After decrement: Address of p variable is 3214864296 </pre> <h2>C Pointer Addition</h2> <p>We can add a value to the pointer variable. The formula of adding value to pointer is given below:</p> <pre> new_address= current_address + (number * size_of(data type)) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will add 2 * number.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will add 4 * number.</p> <p>Let&apos;s see the example of adding value to pointer variable on 64-bit architecture.</p> <pre> #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p+3; //adding 3 to pointer variable printf(&apos;After adding 3: Address of p variable is %u 
&apos;,p); return 0; } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After adding 3: Address of p variable is 3214864312 </pre> <p>As you can see, the address of p is 3214864300. But after adding 3 with p variable, it is 3214864312, i.e., 4*3=12 increment. Since we are using 64-bit architecture, it increments 12. But if we were using 32-bit architecture, it was incrementing to 6 only, i.e., 2*3=6. As integer value occupies 2-byte memory in 32-bit OS.</p> <h2>C Pointer Subtraction</h2> <p>Like pointer addition, we can subtract a value from the pointer variable. Subtracting any number from a pointer will give an address. The formula of subtracting value from the pointer variable is given below:</p> <pre> new_address= current_address - (number * size_of(data type)) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will subtract 2 * number.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will subtract 4 * number.</p> <p>Let&apos;s see the example of subtracting value from the pointer variable on 64-bit architecture.</p> <pre> #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-3; //subtracting 3 from pointer variable printf(&apos;After subtracting 3: Address of p variable is %u 
&apos;,p); return 0; } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After subtracting 3: Address of p variable is 3214864288 </pre> <p>You can see after subtracting 3 from the pointer variable, it is 12 (4*3) less than the previous address value.</p> <p>However, instead of subtracting a number, we can also subtract an address from another address (pointer). This will result in a number. It will not be a simple arithmetic operation, but it will follow the following rule.</p> <p>If two pointers are of the same type,</p> <pre> Address2 - Address1 = (Subtraction of two addresses)/size of data type which pointer points </pre> <p>Consider the following example to subtract one pointer from an another.</p> <pre> #include void main () { int i = 100; int *p = &amp;i; int *temp; temp = p; p = p + 3; printf(&apos;Pointer Subtraction: %d - %d = %d&apos;,p, temp, p-temp); } </pre> <p> <strong>Output</strong> </p> <pre> Pointer Subtraction: 1030585080 - 1030585068 = 3 </pre> <h2>Illegal arithmetic with pointers</h2> <p>There are various operations which can not be performed on pointers. Since, pointer stores address hence we must ignore the operations which may lead to an illegal address, for example, addition, and multiplication. A list of such operations is given below.</p> <ul> <li>Address + Address = illegal</li> <li>Address * Address = illegal </li> <li>Address % Address = illegal</li> <li>Address / Address = illegal</li> <li>Address &amp; Address = illegal</li> <li>Address ^ Address = illegal</li> <li>Address | Address = illegal</li> <li> ~Address = illegal</li> </ul> <h2>Pointer to function in C</h2> <p>As we discussed in the previous chapter, a pointer can point to a function in C. However, the declaration of the pointer variable must be the same as the function. Consider the following example to make a pointer pointing to the function. <pre> #include int addition (); int main () { int result; int (*ptr)(); ptr = &amp;addition; result = (*ptr)(); printf(&apos;The sum is %d&apos;,result); } int addition() { int a, b; printf(&apos;Enter two numbers?&apos;); scanf(&apos;%d %d&apos;,&amp;a,&amp;b); return a+b; } </pre> </p><p> <strong>Output</strong> </p> <pre> Enter two numbers?10 15 The sum is 25 </pre> <h2>Pointer to Array of functions in C</h2> <p>To understand the concept of an array of functions, we must understand the array of function. Basically, an array of the function is an array which contains the addresses of functions. In other words, the pointer to an array of functions is a pointer pointing to an array which contains the pointers to the functions. Consider the following example.</p> <pre> #include int show(); int showadd(int); int (*arr[3])(); int (*(*ptr)[3])(); int main () { int result1; arr[0] = show; arr[1] = showadd; ptr = &amp;arr; result1 = (**ptr)(); printf(&apos;printing the value returned by show : %d&apos;,result1); (*(*ptr+1))(result1); } int show() { int a = 65; return a++; } int showadd(int b) { printf(&apos;
Adding 90 to the value returned by show: %d&apos;,b+90); } </pre> <p> <strong>Output</strong> </p> <pre> printing the value returned by show : 65 Adding 90 to the value returned by show: 155 </pre> <hr></5;>

C でのポインターのデクリメント

インクリメントと同様に、ポインター変数をデクリメントできます。ポインターをデクリメントすると、ポインターは前の位置を指し始めます。ポインタをデクリメントする式は次のとおりです。

 new_address= current_address - i * size_of(data type) 

32ビット

32 ビット int 変数の場合は 2 バイト減ります。

64ビット

64 ビット int 変数の場合は 4 バイト減分されます。

バイナリツリーの順序トラバーサル

64 ビット OS でポインタ変数をデクリメントする例を見てみましょう。

 #include void main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-1; printf(&apos;After decrement: Address of p variable is %u 
&apos;,p); // P will now point to the immidiate previous location. } 

出力

 Address of p variable is 3214864300 After decrement: Address of p variable is 3214864296 

Cポインタの追加

ポインタ変数に値を追加できます。ポインタに値を加算する式は次のとおりです。

 new_address= current_address + (number * size_of(data type)) 

32ビット

32 ビット int 変数の場合、2 * 数値が加算されます。

64ビット

64 ビット int 変数の場合、4 * 数値が加算されます。

64 ビット アーキテクチャでポインタ変数に値を追加する例を見てみましょう。

 #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p+3; //adding 3 to pointer variable printf(&apos;After adding 3: Address of p variable is %u 
&apos;,p); return 0; } 

出力

 Address of p variable is 3214864300 After adding 3: Address of p variable is 3214864312 

ご覧のとおり、p のアドレスは 3214864300 ですが、p 変数で 3 を加算すると、3214864312、つまり 4*3=12 増加します。 64 ビット アーキテクチャを使用しているため、12 ずつ増加します。しかし、32 ビット アーキテクチャを使用している場合は、6 のみ増加します (つまり、2*3=6)。整数値として、32 ビット OS では 2 バイトのメモリを占有します。

カット・ティンプの純資産

Cポインタの減算

ポインタの加算と同様に、ポインタ変数から値を減算できます。ポインタから任意の数値を引くとアドレスが得られます。ポインタ変数から値を減算する式は次のとおりです。

 new_address= current_address - (number * size_of(data type)) 

32ビット

32 ビット int 変数の場合、2 * 数値が減算されます。

64ビット

64 ビット int 変数の場合、4 * 数値が減算されます。

64 ビット アーキテクチャでポインタ変数から値を減算する例を見てみましょう。

 #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-3; //subtracting 3 from pointer variable printf(&apos;After subtracting 3: Address of p variable is %u 
&apos;,p); return 0; } 

出力

 Address of p variable is 3214864300 After subtracting 3: Address of p variable is 3214864288 

ポインタ変数から 3 を減算すると、前のアドレス値より 12 (4*3) 少ないことがわかります。

ただし、数値を減算する代わりに、別のアドレス (ポインター) からアドレスを減算することもできます。これにより数値が得られます。単純な四則演算ではありませんが、次のようなルールに従います。

2 つのポインターが同じ型の場合、

 Address2 - Address1 = (Subtraction of two addresses)/size of data type which pointer points 

あるポインターから別のポインターを減算する次の例を考えてみましょう。

 #include void main () { int i = 100; int *p = &amp;i; int *temp; temp = p; p = p + 3; printf(&apos;Pointer Subtraction: %d - %d = %d&apos;,p, temp, p-temp); } 

出力

 Pointer Subtraction: 1030585080 - 1030585068 = 3 

ポインタを使用した不正な算術演算

ポインタに対して実行できないさまざまな操作があります。ポインタはアドレスを格納するため、加算や乗算など、不正なアドレスにつながる可能性のある演算は無視する必要があります。そのような操作のリストを以下に示します。

  • 住所 + アドレス = 不正です
  • 住所 * アドレス = 不正です
  • アドレス % アドレス = 不正です
  • 住所 / 住所 = 不正です
  • 住所と住所 = 不正です
  • アドレス ^ アドレス = 不正です
  • 住所 |住所 = 不正
  • ~アドレス = 不正です

C の関数へのポインター

前の章で説明したように、ポインターは C の関数を指すことができます。ただし、ポインター変数の宣言は関数と同じである必要があります。関数を指すポインターを作成する次の例を考えてみましょう。

 #include int addition (); int main () { int result; int (*ptr)(); ptr = &amp;addition; result = (*ptr)(); printf(&apos;The sum is %d&apos;,result); } int addition() { int a, b; printf(&apos;Enter two numbers?&apos;); scanf(&apos;%d %d&apos;,&amp;a,&amp;b); return a+b; } 

出力

 Enter two numbers?10 15 The sum is 25 

C の関数の配列へのポインター

関数の配列の概念を理解するには、関数の配列を理解する必要があります。基本的に、関数の配列は関数のアドレスを含む配列です。言い換えれば、関数の配列へのポインタは、関数へのポインタを含む配列を指すポインタです。次の例を考えてみましょう。

 #include int show(); int showadd(int); int (*arr[3])(); int (*(*ptr)[3])(); int main () { int result1; arr[0] = show; arr[1] = showadd; ptr = &amp;arr; result1 = (**ptr)(); printf(&apos;printing the value returned by show : %d&apos;,result1); (*(*ptr+1))(result1); } int show() { int a = 65; return a++; } int showadd(int b) { printf(&apos;
Adding 90 to the value returned by show: %d&apos;,b+90); } 

出力

 printing the value returned by show : 65 Adding 90 to the value returned by show: 155