ソース読解、難度2級
以下のC言語ソースを読み、20文字以内で完結に動作を説明せよ。回答はコメント欄に記入すること。(5点)
a = 0; b = 0; if ((a == 1) || (b == 1)) { abFlag = 1; } else { abFlag = 0; }
変数名は替えたけど、ホントこのままで「実機」のソースとして使われてるんだよなぁ…何がどうしてこうなったんだろうな。
Hinemosu
行きすぎた最先端を目指す hide10 の個人ブログ
以下のC言語ソースを読み、20文字以内で完結に動作を説明せよ。回答はコメント欄に記入すること。(5点)
a = 0; b = 0; if ((a == 1) || (b == 1)) { abFlag = 1; } else { abFlag = 0; }
変数名は替えたけど、ホントこのままで「実機」のソースとして使われてるんだよなぁ…何がどうしてこうなったんだろうな。
また人様のソースを引き継いでしまいました。これを書いた人は while(1) が好きみたいで、あちこちに埋め込んであるのです。どれぐらい好きかというと、こんなコードを見つけちゃったぐらい。
while(1) { if( hoge == 1 ) { break ; } }
意味は分かるけど、正直どうかと思うよね…
それに加えて while(1) はコンパイラさんが「定数値使うな」とインフォメーションを出してくるのであまり好きじゃない。そんなわけでSubversionで分岐したあと、せっせとwhile文を書き直して一人ソースチェックまでやるのですが、本線に戻す勇気が無くて放置してあったり。ユニットテスト出来れば安心だけど、俺様ソースチェックだけじゃイマイチ自身がないのよね。
なぜかまたソースチェックなんてしてるわけですが。0除算が無いか確認しようとして、’/’を探そうとしたんだけどうまくいかない。普通に’/’を探すと、コメントの”//”やら”/*”も引っかかるので、正規表現だ!と意気込んだんだけど…「/[^\*]」とやっても、思うようにいかないんだよなぁ。何かズバッ!と分かる人がいたら教えてプリーズなのです。
void hogehoge() { int a[6] ; for(i=0;i<4;i++) b[i] = a[i] ; }
全部コピーしろよ。
void puge() { int a[7] ; for(i=0;i<64;i++) a[i] = b[i] ; }
コピーしすぎだよ。
何度も言いますが、出荷済製品のソースです…
今日のバグ発見。
a = b < 1
前後を追ってみたらビットシフトしたかったらしい。ホントにこれは出荷済み製品のソースなんだろうか orz
NVRAMへのアクセスも何も考えずに書き込んでるみたいだし…普通二重化するだろうよ。
関数の戻り値としてポインタを返すところで、エラーの場合に (-1) のポインタを返してる。だけど、呼出下ではエラーチェックしてないので、エラーがあると(-1)の領域にアクセスしてる orz
ロジック的にエラーが返らない事を保証してるっぽいけど、そのロジックが危ういからなぁ…
うわ、300行を超える関数で10段ネストしてるよ!何やってるかサッパリわからないさ!気晴らしにTab8で表示させたら、コードの頭のほうしか画面に出ない!すごい!かっこいい!感動した!
引き続き見ていて、なんだか似たような関数があるなぁと内容を見比べてたら、アクセス領域が違うだけで他数十行は全く同一だった。共通部分は切り出してよ…
昨日の日記に書いた謎ソースの解説。
元のソースはこれ。
for(i=0;i<hoge;i++) a = b[i] == 0 ;
これを分かりやすく書くと
for( i = 0 ; i < hoge ; i++ ) { if ( b[i] == 0 ) { a = 1 ; } else { a = 0 ; } }
に展開されると思われます。配列の中身を調べて値が’0’の物にFlag bitを立てたかったみたい。
a はポインタで物理アドレスを指し示しているので、これで IOにピコピコ信号が出るのですよ。
昨日の書き方じゃ誰もわかんないよね。失礼しました。
while( a == 0 ) ;
上記も、知らん人が見たら無限ループで止まっちゃうコードだよな。実際にはaの値は、ソフトと関係なく変化するIOだったり、CPUレジスタ値だったりするから抜けてくれるんだけどね。
ポインタ渡しの構造体のメンバーのポインタに、別の構造体のメンバーの配列の添字に配列を使った物を加算した値で配列を参照されていると、もう何が何やら分かりません。
せっかくC言語で書いてるんだから、もう少し分かりやすく書いて欲しかった orz
つらつらとソースを見ていたら
for(i=0;i<hoge;i++) a = b[i] == 0 ;
なんてのを見つけて、一瞬考えちゃった。もうちょっと分かりやすく書いてくれるといいのに…
配列サイズを越えている箇所が無いかチェックしよう!ということで、配列の添え字に変数を使っている箇所への代入文をリストアップしようとして難航。手抜きだけど
\[[^0-9].*\].*[ |\t|+|-|&|<|>|\|]=[ |\t]
で大分取れるようになった。でもまだ
hoge[3+i] = a ;
みたいのは取れないなぁ、と気が付いたところでタイムアップ。明日もうちょっと考えてみよう。
効率よくソースチェックするなら、自分でやりたいことをまとめた嘘プリプロを作ったほうが早いような気がするなぁ。んでも、ちゃんとしたのを作ろうとするとANSIを読まないといかんかのぅ。
今日も相変わらず駄目ソースの解析。戻り値を参照しているのに、その関数に戻り値がありませんでした。聞いた話しだとSH系だとR0の値が戻り地として使われるみたいだね。どういう動きをするのか正確に把握してないけど、時間があるときにICEで実動作を確認しておいたほうがよさそうだなぁ。