情報処理Ⅱ 2005年10月28日(金) 本日学ぶこと 演算子(Operator) +, -, =, %, ++ ,&& ,||, == など C言語ではどんな演算子が使用できるか? 演算子間の優先順位はどうなっているか? • 例: 1 + 2 * 3 と書けば,(1 + 2) * 3 ではなく 1 + (2 * 3) と解釈される.このとき,* は + よりも 優先順位が高いという. 問題 整数が与えられたとき,そのビットパターンを出力できる? • 例: (char)40 のビットパターンは,00101000 • int型やlong型,float型のビットパターンは? 2 用語説明 演算対象をオペランド(operand)という. 「left value」の略 代入できるオブジェクトを左辺値(lvalue)という. y = x + 1; のとき, x と 1 は,演算子 + のオペランド y と x + 1 は,演算子 = のオペランド 例: p = (++q) + 1; としたときの p と q 演算子を適用して値を得ることを評価という. 例: if (x = 3) {...} としたとき,xに3が代入されると ともに,ifの条件は真となる. 3 演算子のすべて 1. 関数呼び出し( ),配列の添字[ ],構造体のメンバ参照(., ->) 2. 単項演算子(!, 単項*, ++, 単項+, sizeof, キャストなど) 3. 乗除(2項*, /, %) 4. 加減算(2項+, 2項-) 5. シフト(<<, >>) 6. 関係(<, >, <=, >=) 7. 関係(==, !=) 8. ビット演算(&) 9. ビット演算(^) 10. ビット演算(|) 11. 論理演算(&&) 12. 論理演算(||) 13. 3項演算子(? :) 14. 代入演算子(=, +=など) 15. コンマ(,) 高い 優 先 順 位 低い 優先順位を変えたければ,( )で囲む.( )が何重にもなることがある.{ }や[ ]は, この目的で使用できない. 4 2項演算子 アスタリスク 加減算演算子: +, スラッシュ 乗除演算子(1): *, / 乗除演算子(2): % (剰余を求める.オペランドは整数) 関係演算子: <, >, <=, >=, ==, != 暗黙の型変換が起こる場合を除き,オペランドは同一の型で なければならない. ○ × ○ ○ if if if if (2 == 3.14) … ('a' == "abc") … (0x61 == 'a') … ("abc" == "def") … 5 単項演算子 増分演算子,減分演算子: ++, -正負の符号: +, sizeof演算子: sizeof sizeof(char) は 1 char x; に対して sizeof(x) も 1 キャスト演算子: (型名) 実数型やポインタ型の変 数もオペランドにできる. オペランドは変数名,式 もしくは型名. 慣習として ( ) をつけるが, 関数呼び出しではない. ( ) は必須 1/3 は 0 (float)1/3 は 0.333… (float)(1/3) は 0.0 6 単項演算子:注意点 原則として,オペランドの前(左)につける. 増分演算子と減分演算子はオペランドの後ろにつけることも できるが,前につけるのと意味が異なる. x = --y; ⇒ 「y = y - 1; x = y;」 と同じ(減分を先 に評価). x = y--; ⇒ 「x = y; y = y - 1;」 と同じ(減分を後 で評価).(x = y)--; ではない. 増分演算子と減分演算子のオペランドは,左辺値であり,か つ算術型またはポインタ型でなければならない. 7 代入演算子 =, +=, -=, *=, /=, %= など 左側のオペランドは左辺値でなければならない. x + 1 = y; は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; と同じ 8 ビットパターン出力プログラム:準備 対象(入力)は,unsigned char型の値 簡単のため ビット長が分かれば,他の整数型にも容易に拡張可能 x=40 … 0 0 1 0 1 0 0 0 9 ビットパターン出力プログラム(1) 検査方法 xは,2倍してから, 桁あふれを取り除く. x: 0 0 1 0 1 0 0 0 x>=128は偽 ⇒ 0を出力 x: 0 1 0 1 0 0 0 0 x>=128は偽 ⇒ 0を出力 x: 1 0 1 0 0 0 0 0 x>=128は真 ⇒ 1を出力 x: 0 1 0 0 0 0 0 0 x>=128は偽 ⇒ 0を出力 0 0 0 x>=128は偽 ⇒ 0を出力 … x: 0 0 0 0 0 10 論理演算子 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)である. && の左を偽と評価すれば,右は評価しない. || の左を真と評価すれば,右は評価しない. 11 論理演算 x y x && y x || y x !x 真 真 1 1 真 0 偽 真 0 1 偽 1 真 偽 0 1 偽 偽 0 0 偽:整数型なら0,浮動小数点型なら0.0,ポインタ型なら NULLと等しくなる値. 真:偽でないスカラ型(整数型,浮動小数点型もしくはポイン タ型)の値. 12 ビット演算子 整数値をビット(0と1)の並びとみなし,ビット単位 (bitwise)で演算を行う. ビット単位AND: & (2項演算子) ビット単位OR: | (2項演算子) ビット単位XOR: ^ (2項演算子) ビット単位NOT: ~ (単項演算子) 例: 1 & 2 は0である. 優先順位は ~ > & > ^ > | 代入演算子 &=, |=, ^= も利用可能. 13 ビット演算 x y x&y x|y x^y x ~x 1 1 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 0 0 0 0 0 ビット単位の演算結果であることに注意. 0 ^ 1 = 1 ^ 0 = 1 (相補律) 1 ^ 1 = 0 (ビットの反転), x ^ x = 0 (ビットのクリア)が成り立つ. 14 ビット演算子の利用例 一部のビットを0にする. 一部のビットを1にする. x & 0x0f : 00000011 x | 0x0f : 00101111 x ^ 0x0f : 00101100 char x = 0x23; のとき x ^ 0x0f は 0x2c,x ^ 0xf0 は0xd3. 全部のビットを反転する. 0x0f : 00001111 char x = 0x23; のとき x | 0x0f は 0x2f,x | 0xf0 は0xf3. 一部のビットを反転する. char x = 35; のとき x & 0x0f は 3,x & 0xf0 は32. x=35 : 00100011 ~x : 11011100 x = ~x; とすればよい. 15 シフト演算子 整数値をビットの並びとみなす. いずれも2項演算子で,左は整数値,右はシフトするビット数 (0以上の整数値). 左シフト: << 右シフト: >> 5 << 3 は 40 m << n は m×2n m >> n は m×2-n 5 → 00000101 ← 40 >> 3 5 << 3 → 00101000 ← 40 負の数を右シフトしたときの結果は処理系依存. 代入演算子 <<=, >>= も利用可能. 16 ビットパターン出力プログラム(2) 検査方法 x: 0 0 1 0 1 0 0 0 bの初期値は,1 << 7 bの「増分」は,b >>= 1 xの値は変化しない b: 1 0 0 0 0 0 0 0 x & bは0 ⇒ 0を出力 b: 0 1 0 0 0 0 0 0 x & bは0 ⇒ 0を出力 b: 0 0 1 0 0 0 0 0 x & bは非0 ⇒ 1を出力 0 0 1 x & bは0 ⇒ 0を出力 … b: 0 0 0 0 0 17 3項演算子 オペランド1 ? オペランド2 : オペランド3 例: t = (a > b) ? a : b; ⇒ if (a > b) t = a; else t = b; 演算結果は左辺値ではない まずオペランド1を評価する.それが真であればオペランド2を, 偽であればオペランド3を評価して,その値を演算結果とする. × a > b ? a : b = 10; ○ *(a > b ? a : b) = 10; a, bはポインタ変数 3項演算子の入れ子も可能だが,読みにくい 18 その他の演算子 関数呼び出し: ( ) 配列の添字: [ ] コンマ演算子: , 例: for (i = 0, p = function(p[i], 1); i < 10; i++) これらは構文の一部であり,演算子ではない. 19 代入の順序について オペランドの評価順序は,特に明記したものを除いて,不定 (処理系依存)である.式の中で同一のオブジェクトに2つ以 上の代入をしないよう心がける. 例: x=2; printf("%d %d", ++x, ++x); の出力は 「3 4」かもしれないし,「4 3」かもしれない. 例: x % 2 ? (x = x * 3 + 1) : (x /= 2); は意 図通りに動作する(が,if文で書くほうが自然). 20 まとめ Cでは多彩な演算子が利用できる.いくつかは数学の記号に 近く,いくつかはC独特である. 演算子ごとに「優先順位」と「結合の方向」が決まっている. 真偽の扱い,評価されない式にも注意する. 21
© Copyright 2024 ExpyDoc