230 likes | 339 Views
情報処理 Ⅱ. 第6回:2003年11月25日(火). レポート総評(1). 「メタ」を持つ様々な用語があった. メタクラス ; メタコンピュータ ; メタサーチ ( エンジン ), メタ検索 ( エンジン ); メタデータ ; メタディレクトリ ; メタファイル ; メタプログラム ; メタボール ; メタミュージック ; メタ情報 ; メタ文字 , メタキャラクタ ; (UML) メタモデル ; HTML の META タグ ; META キー (Emacs で使用する ) 「メタ」に関する興味深い記述が見られた.
E N D
情報処理Ⅱ 第6回:2003年11月25日(火)
レポート総評(1) • 「メタ」を持つ様々な用語があった. • メタクラス; メタコンピュータ; メタサーチ(エンジン), メタ検索(エンジン); メタデータ; メタディレクトリ; メタファイル; メタプログラム; メタボール; メタミュージック; メタ情報; メタ文字, メタキャラクタ; (UML)メタモデル; HTMLのMETAタグ; METAキー (Emacsで使用する) • 「メタ」に関する興味深い記述が見られた. • メタというのは相対的な考えであり,自分がどこを視点として選ぶかによって推移するものです.(http://www.ogis-ri.co.jp/otc/hiroba/technical/Squeak4/pdf/Squeak4.pdf)
レポート総評(2) • 体裁として不適切なものがあった. • B5ルーズリーフでの提出 • 2枚を超えている • ノンブル(ページ番号)がない • 左上をステープラで綴じていない • 敬体(です体)で書いている • 行間あけすぎ • 用紙の裏に,レポートと関係ない図面らしきもの • Webページやコマンド解説文書を引き写しただけ
問題(授業がつまらない人のために) • 整数値の2進表現を出力するプログラムを作成せよ.整数値の型(int, char, longなど)も考慮せよ. • 例: char型の40 ⇒ 00101000 • 次の3つの式の中で,同じ動作をするのはどれとどれか? • *p++ = *q++; • *(p++) = *(q++); • (*p)++ = (*q)++;
演算子(Operator) • これまで使用してきた演算子 • +, -, =, +=, ++, *, &, [ ] など • 学ぶこと • C言語ではどんな演算子が使用できるか? • 演算子間の優先順位はどうなっているか? • 例: 1 + 2 * 3 と書けば,(1 + 2) * 3 ではなく1 + (2 * 3) と解釈される.このとき,* は + よりも優先順位が高いという.
用語説明 • 演算対象をオペランド(operand)という. • y = x + 1; のとき,x と1 は,演算子 + のオペランドy と x + 1 は,演算子 = のオペランド • 代入できるオブジェクトを左辺値(lvalue)という. • *p = (++q) + 1;としたときの *p と q は左辺値である. • &x や,int z[10]; としたときの z は左辺値ではない. 「left value」の略
2項演算子 • 加減算演算子: +, - • 乗除演算子(1): *, / • 乗除演算子(2): %(剰余を求める.オペランドは整数) • 関係演算子: <, >, <=, >=, ==, != • 暗黙の型変換が起こる場合を除き,オペランドは同一の型でなければならない. • char *x; int y; に対して,if (x <= y) はNG,if (*x <= y) はOK.
単項演算子 • 間接演算子: * • アドレス演算子: & • 増分演算子,減分演算子: ++, -- • 正負の符号: +, - • sizeof演算子: sizeof • sizeof(char) は1,char x; に対して sizeof(x) も1.しかし sizeof('0') は sizeof(int) と同じ値になる. • キャスト演算子: (型名) • 1/3は0.しかし,(double)1/3 は 0.333…となる.さらに,(double)(1/3) は 0.0 となる. オペランドは変数名,式もしくは型名. 慣習として ( ) をつけるが, 関数呼び出しではない. ( ) は必須
単項演算子:注意点(1) • 原則として,オペランドの前(左)につける. • 右から左に結合する. • **p は,*(*p) である.つまり右側の演算子*を評価してから左側を評価する. • 参考: a * b * c は (a * b) * c である.つまり左側の演算子*を評価してから右側を評価する.
単項演算子:注意点(2) • 増分演算子と減分演算子はオペランドの後ろにつけることもできるが,前につけるのと意味が異なる. • x = ++y; ⇒ y = y + 1; x = y; と同じ(増分を先に評価) • x = y++; ⇒ x = y; y = y + 1; と同じ(増分を後で評価) • 増分演算子と減分演算子のオペランドは,左辺値であり,かつ算術型またはポインタ型でなければならない. • sizeof演算子のオペランドは式として評価されない. • sizeof(x++) としても x の値は増えない.
代入演算子 • =, +=, -=, *=, /=, %= • x 記号= y; は,x = x 記号 y; と同じ. • 左側のオペランドは左辺値でなければならない. • x + 1 = y; や (*p)++ = (*q)++; はNG. • 右から左に結合する. • x += *y = z + 2; ⇒ *y = z + 2; x += *y; と同じ. • 左辺値に格納される値を演算結果とする.暗黙の型変換に注意. • double d; int x; に対してx = d = 1./3.; とすると,d = 0.333…; そして x = 0;d = x = 1./3.; とすると,x = 0; そして d = 0.0;
int a[10]; … if (x >= 0 && x < 10 && a[x] == y) とすると,x<0 や x≧10のときは a[x] == y を評価しない. 論理演算子 • AND: &&(2項演算子) • OR: ||(2項演算子) • NOT: !(単項演算子) • 優先順位は ! > && > || • 真偽とC言語での表現 • 真: 0以外に評価される値 • 偽: 0に評価される値 • 例: 1 && 2は真(具体的には,1)である. • &&の左を偽と評価すれば,右は評価しない. • ||の左を真と評価すれば,右は評価しない.
論理演算 • 偽:整数型なら0,浮動小数点型なら0.0,ポインタ型ならNULLと等しくなる値. • 真:偽でないスカラ型(整数型,浮動小数点型もしくはポインタ型)の値. x y x && y x || y x !x 真 真 1 1 真 0 偽 真 0 1 偽 1 真 偽 0 1 偽 偽 0 0
ビット演算子 • 整数値をビット(0と1)の並びとみなし,ビット単位(bitwise)で演算を行う.いずれも2項演算子. • ビット単位AND: & • ビット単位OR: | • ビット単位XOR: ^ • 例: 1 & 2は0である. • 優先順位は & > ^ > | • 代入演算子 &=, |=, ^=も利用可能.
ビット演算 • ビット単位の演算結果であることに注意. • 0 ^ 1 = 1, 1 ^ 1 = 0 (ビットの反転)x ^ x = 0 (ビットのクリア)が成り立つ. x y x & y x | y x ^ y 1 1 0 1 1 0 1 1 0 1 0 1 1 1 0 0 0 0 0 0
ビット演算子の利用例 • 一部のビットを0にする. • char x = 35; のとき x & 0x0f は3,x & 0xf0 は32. • 一部のビットを1にする. • char x = 0x23; のとき x | 0x0f は0x2f,x | 0xf0 は0xf3. • 一部のビットを反転する. • char x = 0x23; のとき x ^ 0x0f は0x2c,x ^ 0xf0 は0xd3. • 変数 x の全部のビットを(手っ取り早く)反転する. • x ^= -1; とすればよい.
シフト演算子 • 整数値をビットの並びとみなす. • 左シフト: << • 右シフト: >> • いずれも2項演算子で,左は整数値,右はシフトするビット数(0 以上の整数値). • 5 << 3は40. • 負の数を右シフトしたときの結果は処理系依存. • 代入演算子 <<=, >>=も利用可能. 5 → 00000101 ← 40 >> 3 5 << 3 → 00101000 ← 40
例題1 • 整数値の2進表現を出力するプログラム • 1 && 2 と 1 & 2 を比較する. • これまでに書いた論理演算・ビット演算の例を検証する.
その他の演算子 • 関数呼び出し: ( ) • 配列の添字: [ ] • コンマ演算子: , • 例: for (i = 0, p = base; function(p[i], 1); i++) これらは構文の一部であり,演算子ではない.
演算子の優先順位 • 関数呼び出し( ),配列の添字[ ] • 単項演算子(!, 単項*, ++, 単項+, sizeof, キャストなど) • 乗除(2項*, /, %) • 加減算(2項+, 2項-) • シフト(<<, >>) • 関係(<, >, <=, >=) • 関係(==, !=) • ビット演算(&) • ビット演算(^) • ビット演算(|) • 論理演算(&&) • 論理演算(||) • 3項演算子(?:) • 代入演算子(=, +=など) • コンマ(,) 高い 低い • 優先順位を変えたければ,( )で囲む.( )が何重にもなることがある.{ }や[ ]は,この目的で使用できない.
まとめ • C言語では多彩な演算子が利用できる.いくつかは数学の記号に近く,いくつかはC言語独特である. • 各演算子には優先順位がある. • 同じ優先順位の演算の評価順序を決めるのは,結合の方向である(演算子により,「左から右」か「右から左」かが決まっている). • 評価されない式に注意.
発展的な話題:代入の順序について • 冒頭の問題に対する解答 • *p++ = *q++; と *(p++) = *(q++); と*p = *q; p++; q++; は同じ. • オペランドの評価順序は,特に明記したものを除いて,不定(処理系依存)である.式の中で同一のオブジェクトに2つ以上の代入をしないよう心がける. • function(++c, ++c); はfunction(c + 1, c + 2); ++c; ++c; かもしれないし,function(c + 2, c + 1); ++c; ++c; かもしれない.
発展的な話題:3項演算子 • オペランド1 ?オペランド2 :オペランド3 • まずオペランド1を評価する.それが真であればオペランド2を,偽であればオペランド3を評価して,その値を演算結果とする. • 例: t = (a > b) ? a : b; ⇒ if (a > b) t = a; else t = b; • a > b ? a : b = 10; はNG(コンパイルエラー).しかし *(a > b ? a : b) = 10; はOK.