情報処理Ⅱ 第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 は,演算子 = のオペランド 「left value」の略 代入できるオブジェクトを左辺値(lvalue)という. *p = (++q) + 1; としたときの *p と q は左辺値である. &x や,int z[10]; としたときの z は左辺値ではない. 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 + 1 = y; や (*p)++ = (*q)++; はNG. 右から左に結合する. x 記号= y; は,x = x 記号 y; と同じ. 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; 論理演算子 AND: && (2項演算子) OR: || (2項演算子) NOT: ! (単項演算子) 優先順位は ! > && > || 真偽とC言語での表現 int a[10]; … if (x >= 0 && x < 10 && a[x] == y) とすると,x<0 や x≧10のときは a[x] == y を評価しない. 真: 0以外に評価される値 偽: 0に評価される値 例: 1 && 2は真(具体的には,1)である. &&の左を偽と評価すれば,右は評価しない. ||の左を真と評価すれば,右は評価しない. 論理演算 x y x && y x || y x !x 真 真 1 1 真 0 偽 真 0 1 偽 1 真 偽 0 1 偽 偽 0 0 偽:整数型なら0,浮動小数点型なら0.0,ポインタ型な らNULLと等しくなる値. 真:偽でないスカラ型(整数型,浮動小数点型もしくは ポインタ型)の値. ビット演算子 整数値をビット(0と1)の並びとみなし,ビット単位 (bitwise)で演算を行う.いずれも2項演算子. ビット単位AND: & ビット単位OR: | ビット単位XOR: ^ 例: 1 & 2は0である. 優先順位は & > ^ > | 代入演算子 &=, |=, ^= も利用可能. ビット演算 x y x&y x|y x^y 1 1 1 1 0 0 1 0 1 1 1 0 0 1 1 0 0 0 0 0 ビット単位の演算結果であることに注意. 0 ^ 1 = 1, 1 ^ 1 = 0 (ビットの反転) x ^ x = 0 (ビットのクリア)が成り立つ. ビット演算子の利用例 一部のビットを0にする. 一部のビットを1にする. char x = 0x23; のとき x | 0x0f は0x2f,x | 0xf0 は0xf3. 一部のビットを反転する. char x = 35; のとき x & 0x0f は3,x & 0xf0 は32. 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++) これらは構文の一部であり,演算子ではない. 演算子の優先順位 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 関数呼び出し( ),配列の添字[ ] 単項演算子(!, 単項*, ++, 単項+, 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.
© Copyright 2024 ExpyDoc