コンパイラ 2012年10月29日 酒居敬一@A468([email protected]) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2012/index.html 1 意味解析 前回までの内容 構文解析では表面的な形式の整合性だけを見た。 「識別子名=識別子名+識別子名」と推定された式があったとして、 識別子名が変数名なのか関数名なのかは関知しない、では片手落ち。 今回の内容 各字句の意味に立ち入った解析とエラーチェックを行う。 2 識別子を変数・関数・配列・定数などに区別する。 そのための名前表に要求される情報を明らかにする。 実際の例を挙げる。 名前表 何の名前か? 変数・関数・仮引数・定数・一時変数・自動変数など。 型 整数・実数・文字・文字列・配列・関数・構造型など。 語長 1バイト・2バイト・4バイト・8バイト スカラー・ベクター。 種別 全域的・ブロックなど。永続的・一時的・自動的など。 アドレス 対応するソースプログラム中の行・桁 3 名前表を使ったエラーチェック 二重宣言のチェック 同じ名前が2度定義されてるとエラー。 ただし、通用範囲外に関してはエラーにならない場合が多い。 未定義チェック 通用範囲内に参照する名前の物がなければエラー。 左辺値チェック 代入文・代入式の左辺に代入可能な物が置かれているか? 型の整合性チェック 4 型が同一視できるかどうか? 型を自動変換してもいいかどうか? なお、ここでできるのは静的な型チェックのみ。 名前表の探索1 名前から表中の該当エントリを探さないといけない。 線形探索 探索にO(n)必要。アルゴリズムは単純。 二分探索 探索はO(n)必要。追加・削除を考え、構造型データで木を生成。 ハッシュ 開番地法 分離連鎖法 5 名前の個数が配列の大きさまでという制約を受けてしまう。 衝突が起きても使い続けることができる。一般的な方法。 スコープ(通用範囲) CやJavaでは、名前の通用範囲が決まっている。 ファイルやブロックといった単位で範囲を決めている。 通用範囲の外側では、内側で定義した物は存在しない。 同じ通用範囲内で同名の物を定義するとエラー。 通用範囲の外側の物と同名の物を内側で定義することは可。 この場合、その名前で最も内側の物が見える。 名前表の名前は通用範囲と組み合わせる必要がある。 参照しようとしている場所から範囲外へ参照対象を探す。 ストレージクラスと通用範囲は別の概念。 6 ストレージクラス:自動変数・静的変数・インスタンス変数 通用範囲:全域・ファイル・クラス・ブロック 名前表の探索2 通用範囲ごとの名前表へのポインタをスタックに置く。 通用範囲に入ったら新しい名前表をスタックへプッシュ。 通用範囲から出たらポップ。 名前はスタックトップ側の名前表から、ボトム側の名前表へ 順に調べていく。 スタックボトム 全域 ファイル 関数 ブロック1 ブロック2 7 スタックトップ 例:数 Cの場合を取り上げる。 float x = 1.0;としておきます。 sizeof(float)とsizeof(long)は同じ4バイトとします。 sizeof(char)は1バイトとします。 式 その値 型 1/10 0 整数 1/10.0 0.1 浮動小数点数 x+33554432 33554432.0 浮動小数点数 (long)x + 33554432 33554433 整数 *((long *)(&x)) 0x3F800000 整数 0x3F800000 1065353216 整数 (char)-1 0b11111111 整数 (unsigned char)0xFF 0b11111111 整数 1==2 0 整数 8 キャストのルール(抜粋) 整数の格上げ 元の型(char, short)のすべての値がintで表せればintに、 unsigned intで表せればunsigned intに変換する。 整数と浮動小数点数 浮動小数点数を整数に変換するとき、小数部分は切り捨て。 整数を浮動小数点数に変換するとき、最も近い値に変換。 浮動小数点型 より精度の高い型に変換するとき、値は不変。 より精度の低い型に変換するとき、表現可能な近い値に変換。 算術変換 9 2項のうち大きなほうの型に変換される。 2項のうち精度の高いほうの型に変換される。 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. #include <stdio.h> ひどいプログラムの例 extern int a, b, c; int hoge(int x) { return x + 100.0; } int main() { int c; unsigned int i; c = hoge(a); hoge = b; for(i = 6; 0 <= i; i--){ printf("Hello!\n"); } return main; } [sakai@star 2011]$ gcc -Wall -Wextra hoge.c hoge.c: In function `main': hoge.c:16: error: invalid lvalue in assignment hoge.c:18: warning: comparison of unsigned expression >= 0 is always true hoge.c:21: warning: return makes integer from pointer without a cast 10 演習(予習) 学生番号:____________ 名前:______________ 1. C言語で全域的な変数を定義したとする。 int int 2. この定義がコンパイラにより次のように翻訳された。 a: b: 3. a = 20; b[3] = {1, 2, 3}; .word .word これらを次のように使うとエラーになる場合があった。 どこがエラーになるでしょうか?その理由は? int *p = b; a = 1; b = 9; p += a; a = p[0] + b[1]; 11 20 1, 2, 3
© Copyright 2024 ExpyDoc