e34.c
if 文の中がカラッポ!





if(val ==1) 誤って『;』を記述した
{
ここには必ず来る
}
解説
詳細は、
C-FAQ 10.4J 16.1J 20.14J
C-FAQ 16.1E
を参照して下さい。
事例紹介1 危険なマクロ:
マクロ使用時、セミコロン記述し忘れると、
次の行がelse節になる。
────定義側─────────────
#define MACRO(arg1,arg2) if(1) {¥
松 ; ¥
竹 ; ¥
梅 ; ¥
} else /* セミコロン無し */
────参照側─────────────
MACRO /* セミコロン忘れた */
ビックリelse節 ;
事例紹介2
『省略時のelseを必ず記述する事』と言う先輩の教えが形骸化したもの、
この様なelseを推奨する文献を私は知らない。
if(松) {
処理色いろ ;
} else ;
if(竹) {
処理色いろ ;
} else ;
if(梅) {
処理色いろ ;
} else ;
先輩が言いたかったのは、
if(松) {
処理色いろ ;
} else if(竹) {
処理色いろ ;
} else if(梅) {
処理色いろ ;
} else { /* このelseの事だと思う */
異常処理
}
蛇足であるが、elseをづらづら記述するより、switch文の方が処理速度が早い。
switch(木) {
case 松: 処理色いろ ; break ;
case 竹: 処理色いろ ; break ;
case 梅: 処理色いろ ; break ;
default: 異常処理 break ;
}
事例紹介3 巨大マクロ
高速化するために、
巨大マクロを作成してもコンパイラの最適化の邪魔になるだけで
苦労の割りにむくわれない。
巨大マクロ関数化した方が良い。
もしくは分割する。
修正前:
#define huge(ARG) { ¥
switch(ARG) { ¥
case 松: ¥
巨大処理 ; ¥
case 竹: ¥
巨大処理 ; ¥
case 梅: ¥
巨大処理 ; ¥
}
}
修正後:
#define huge_松() {松処理 }
#define huge_竹() {竹処理 }
#define huge_梅() {梅処理 }
/************************************************************************/
/******* *********/
/******* *********/
/******* マクロは推奨しないが、 *********/
/******* どうしてもマクロを使用したい時はこのスタイル *********/
/******* *********/
/******* 1999.10.29 *********/
/******* 初版 NEC通信システム *********/
/******* *********/
/************************************************************************/
#include
#include
char buf1[0x7fff] ;
char buf2[0x7fff] ;
struct tag {
int cnt ;
struct tag2 {
char foo ;
char bar ;
char baz ;
char dmy ;
} req[1] ;
} ;
/********************************************************/
/* 推奨しないマクロ */
/********************************************************/
#define badMAC() ¥
if(1) { ¥
tp->req[tp->cnt].foo = 'm' ; ¥
tp->req[tp->cnt].bar = 'a' ; ¥
tp->req[tp->cnt].baz = 'c' ; ¥
} else /* セミコロン無し */
/********************************************************/
/* どうしてもマクロを使用した時はこのスタイル */
/********************************************************/
#define goodMAC() ¥
do { ¥
register _i_ = tp->cnt ; ¥
tp->req[_i_].foo = 'm' ; ¥
tp->req[_i_].bar = 'a' ; ¥
tp->req[_i_].baz = 'c' ; ¥
} while(0)
/********************************************************/
/* 呼び側関数群 */
/********************************************************/
static void bad(struct tag *tp)
{
badMAC() ; badMAC() ; badMAC() ;
}
static void good(struct tag *tp)
{
goodMAC() ; goodMAC() ; goodMAC() ;
}
int main()
{
int i ;
struct tag *p1 = (void *)buf1 ;
struct tag *p2 = (void *)buf2 ;
for(i = 0 ; i < 128 ; i++) {
p1->cnt = i ; good(p1) ;
p2->cnt = i ; bad (p2) ;
if(memcmp(buf1,buf2,sizeof(buf1))) {
printf("%d¥n",i) ; fflush(stdout) ;
abort() ;
}
}
return(0) ;
}
/usr/abiccs/bin/cc -Kopt=2 vs.c -o vs
pixie ./vs -o vs.P
pixie registers: r31, r30, and r19.
old code = 2896 bytes, new code = 10344 bytes (3.6x)
vs.P
prof -pixie vs vs.Addrs vs.Counts
対戦結果
----------------------------------------------------------------------------
* -p[rocedures] using basic-block counts; *
* sorted in descending order by the number of cycles executed in each *
* procedure; unexecuted procedures are excluded *
----------------------------------------------------------------------------
11760 cycles
cycles %cycles cum % cycles bytes procedure (file)
/call /line
5888 50.07 50.07 46 ? bad (vs.c)
3072 26.12 76.19 24 ? good (vs.c)
2716 23.10 99.29 2716 ? main (?)
56 0.48 99.76 56 ? _start (?)
13 0.11 99.87 13 ? _fini (?)
13 0.11 99.98 13 ? _init (?)
2 0.02 100.00 2 ? __zeromem (?)