組み込みC/C++

C/C++リテラシー向上のためのページ

ポインタでやってしまうミス③

ポインタというよりかは、演算子の優先順位に関する物ですが、ミスしがちかなと思いましたので切り取っておきます。

 

Pattern 4

#include <stdio.h>

void mesurement(unsigned int *iChk, unsigned char cNum);

int _tmain(int argc, _TCHAR* argv[ ])
{
    unsigned int iChk[ ]={0};
    
    mesurement(iChk, 5);
    
    for(int i=0; i<10; i++){
	   printf("iChk[%d]=%d\n", i,iChk[i] );
	}
    return 0;
}

void mesurement(unsigned int *iChk, unsigned char cNum)
{
    for(int i=0; i<10; i++, iChk++)
    {
    	if(i==cNum){
           *iChk ++;
	}
    }
}

 あまり良い例ではないのですが、関数mesurementで番号cNum目の配列iChkのカウントをインクリメントするプログラムです。このプログラムは正常にコンパイルが通るのですが、今言った意図通りには動きません。問題は*iCk++;にあります。二項+演算子などの演算子より間接参照演算子*の方が通常は優先順位が高いのですが、後置増分演算子++や後置減分演算子--は間接参照演算子*より優先順位が高く、該当の書き方ではポインタをインクリメントして中身を参照するだけ(隣のアドレスを参照するだけ)でRAMには何も処理しません。中身に対してインクリメントを働かしたいなら括弧をつける必要があります。(*iChk)++; なんとなく間接参照演算子の方が++より優先順位が高そうなのですが、ポインタの取り扱いには括弧を意図的につけるのがよさそうです。

 

試験プログラム

#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{    
	unsigned short time[10] = {10,20,30,40,50,60,70,80,90,100};
	unsigned short *wdTimer1 = time;
	unsigned short *wdTimer2 = time;

	printf("time addr=%d \n", time);

	printf("wdTimer1 addr=%d, entity=%d\n", wdTimer1, *wdTimer1);
	printf("wdTimer2 addr=%d, entity=%d\n", wdTimer2, *wdTimer2);

	*wdTimer1 = *wdTimer1 + 1; 

	printf("wdTimer1 addr=%d, entity=%d\n", wdTimer1, *wdTimer1);

	*wdTimer2 ++; 

	printf("wdTimer2 addr=%d, entity=%d\n", wdTimer2, *wdTimer2);

	return 0;
}

上のプログラムを見る事で *wdTimer1 = *wdTimer1 + 1;という書き方であれば、*より+の方が優先順位が低く*wdTimer2 ++; という書き方であれば*より+の方が優先順位が高いという事が確認出来るかと思います。

 

可読性やセマンティックスという観点では今回のPattern4はiChk[i]++; という書き方が良いかと思います。括弧()は可読性を下げますし、かといってa = a+1; では冗長に感じてしまいます。演算子の優先順位は意外に把握できていないものですから、優先順位を知っている事を前提としたプログラムは他の人に意図が伝わりにくいかと思います。その場に合わせたシンタックスシュガーを使うなどして、人にやさしいプログラムを心掛けるのが良いかと思います。