情報処理II

情報処理Ⅱ
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