*pa++;を実行すると,まずpa++が実行され,*paによりポイント先のデータを参照するようだ.
(ここが変だよC言語〈上〉, p.202)
書き方の問題なのですが,上記では「*paにより『pa++が実行されたあとのpaの値を使って』ポイント先のデータを参照する,と読めてしまいます.これだと,*++pa;と変わりません.
規格を調べてみました.
JIS X 3010:2003, 6.5.2.4 (p.54)には,「後置++演算子の結果は,そのオペランドの値とする.結果を取り出した後,オペランドの値を増分する」とあります.
++とポインタが混在する式では,++を用いない式に置き換え*1ながら,「何に対して1増やすか?」「いつ1増やすか?」を理解すれば,間違いが減ると思われます.
以下の引用もみな,上記と同じページからです.
ここも,この文だけでは,何に対して「++を実行している」かがつかみにくいです*2.
繰り返しになりますが,「*pa++;」,「*++pa;」,「++*pa;」の違いを説明するにあたり,それぞれの++演算子のオペランドが何なのかを確認するのが,不可欠でしょう.
- 「*pa++;」は,paが++演算子のオペランドであり,「*pa;」という(意味のない)文と,「pa = pa + 1;」に分割できます.
- 「*++pa;」も,paが++演算子のオペランドです.前置なので,まず「pa = pa + 1;」としてから,その更新されたpaを使って「*pa;」という(意味のない)文になります.
- 「++*pa;」については,*paが++演算子のオペランドです.「*pa = *pa + 1;」と等価です.
改めて演算子の優先順位を確かめると,++は*より高い優先順位を持つようだ.
多くの書籍で,同じ優先順位としてto prioritize them equally記載されています.
構文を見ると(例えば『C言語によるプログラミング―スーパーリファレンス編』p.171),前置++と単項*は同じ箇所で記載されています.後置++は単項*より上位にありますが,評価方法(意味)はすでに述べた通りです.
しかし,世の中の多くのプログラムで当たり前のように*pa++;と書かれている例をよく見かける.
個人的にあまり好きではなく,授業でも教えている年と教えていない年があるのですが*3,世の中どんなもんか,自分なりに調べてみました.
- 『組込みソフトウェア開発向けコーディング作法ガイド[C言語版] (SEC BOOKS)』*4のp.85には,「M3.3.3 (2)真偽を求める式の中で代入演算子を使用しない.ただし慣習的に使う表現は除く」として,「while (c = *p++)」という例が紹介されています.
- K&Rを見てみましょう.『プログラミング言語C 第2版 ANSI規格準拠』p.129に,「while (*s++ = *t++)」という例がありました.英語版の『C Programming Language (Prentice Hall Software)』だと,p.106です.どちらの本に,このコードの前に「while ((*s++ = *t++) != '\0')」というのも書かれています.「while (*s++ = *t++)」の書き方については,「こうした慣用法はマスターすべきである(the idiom should be mastered)」と肯定的にとらえられています.