授業/C言語基礎/演算子の高度な使い方
をテンプレートにして作成
開始行:
これまでの勉強で、演算子は必要に応じて少しずつ出てきまし...
ここでは、演算子について、まだ説明していない部分を説明し...
*オペランド [#m77529e0]
演算の対象となる値や変数を''オペランド''といいます。
オペランドが1つの演算子を''単項演算子''、2つのものを''2項...
*増分・減分演算子の前置と後置 [#a54f1eaf]
単項演算子である増分演算子 ''++'' は、オペランドの値を1増...
同じく単項演算子である減分演算子 ''--'' は、オペランドの...
増分・減分演算子は、演算子をオペランドの前に置くこと(前...
''前置''のとき、増分・減分演算子を含む式や命令文は、増分...
''後置''のとき、増分・減分演算子を含む式や命令文は、増分...
次のプログラムは、増分演算子を前置と後置で使用しています...
#geshi(c){{
int i = 0;
printf("%d\n", ++i);
printf("%d\n", i++);
printf("%d\n", i);
}}
最初のprintf関数は、前置の増分演算子なので、先に増分演算...
次のprintf関数は、後置の増分演算子なので、先にprintf関数...
したがって、このプログラムを実行すると、次のようになりま...
#geshi(sh){{
luna% a.out
1
1
2
}}
**演習1 [#e25f652b]
プログラム1を作成し、実行結果を確認せよ。
*ビット単位の演算子 [#jc89f6fc]
データは、すべて2進数のビット列で表されています。
そこで、整数を表す2進数のビット列に対してビット単位で演算...
|優先順位|演算子|使用例|意味|h
|2|˜|˜a|補数|
|6|<<|a << b|左シフト|
|~|>>|a >> b|右シフト|
|9|&|a & b|ビット論理積|
|10|^|a ^ b|ビット排他的論理和|
|11|||a | b|ビット論理和|
補数以外の演算子には、複合代入演算子 <<=, >>=, &=, ^=, |=...
**補数 [#be12c9b2]
補数演算子 ''˜'' は、すべてのビットを反転させます(...
#geshi(c){{
int i = 0x80000010;
int j = ~i
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
7fffffef
}}
**左シフト、右シフト [#u4be1562]
左シフト演算子 ''<<'' はビット列を指定された数だけ左にシ...
1ビット左にシフトするごとに、値は2倍になります。
右シフト演算子 ''>>'' はビット列を指定された数だけ右にシ...
1ビット右にシフトするごとに、値は半分になります。
左オペランドが符号なし整数または符号付き整数で先頭ビット...
左オペランドが符号付き整数で先頭ビットが 1(値が負)のと...
#geshi(c){{
unsigned int ui = 0x00000010;
signed int si = 0x80000010;
printf("%08x, %08x\n", ui, si);
printf("%d, %d\n", ui, si);
ui = ui << 1;
si = si << 1;
printf("%08x, %08x\n", ui, si);
printf("%d, %d\n", ui, si);
}}
#geshi(sh){{
luna% a.out
00000010, 80000010
16, -2147483632
00000020, 00000020
32, 32
}}
**論理積 [#i62e1f15]
ビット単位の論理積演算子 ''&'' は、ビットごとに論理積を取...
論理演算子の論理積演算子 ''&&'' と間違えないよう注意しま...
1 と論理積を取るとそのビットは保存され、0 と論理積をとる...
この性質を利用して、上位ビットや下位ビットだけを取り出す...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i & 0x0000ff;
printf("%08x\n", j);
}}
**論理和 [#y37b82de]
ビット単位の論理和演算子 ''|'' は、ビットごとに論理和を取...
論理演算子の論理和演算子 ''||'' と間違えないよう注意しま...
1 と論理和をとるとそのビットは 1 になり、0 と論理話をとる...
この性質を利用して、特定のビットだけを1にする操作に用いら...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i | 0x0000ff;
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
aaaaaaaa
aaaaaaff
}}
**排他的論理和 [#ja94dc04]
ビット単位の排他的論理和演算子 ''^'' は、ビットごとに排他...
1 と排他的論理和をとるとそのビットは反転し、0 と排他的論...
この性質を利用して、ビット列を部分的に反転させる操作に用...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i ^ 0x0000ff;
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
aaaaaaaa
aaaaaa55
}}
また、2つ以上のビットの排他的論理和を求めると、ビットに含...
#geshi(c){{
int i = 1 ^ 1 ^ 1 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0;
printf("%d\n", i);
int j = 1 ^ 1 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0;
printf("%d\n", j);
}}
#geshi(sh){{
luna% a.out
1
0
}}
**演習2 [#oab755e9]
プログラム2からプログラム7を作成し、実行結果を確認せよ。
*論理演算子の短絡評価 [#ff7a051e]
論理演算子の論理積 ''&&'' は、いずれかが偽 (0) のときは結...
そこで、論理積演算子は、左側のオペランドを先に評価し、結...
同様に、論理演算子の論理和 ''||'' は、いずれか...
そこで、論理和演算子は、左側のオペランドを先に評価し、結...
これを、論理演算子の''短絡評価''といいます。
この性質を利用して、除算を行う前に割る数が 0 でないことを...
#geshi(c){{
int i = 0;
(i > 0) && printf("正\n");
(i > 0) || printf("0または負\n");
}}
#geshi(sh){{
luna% a.out
0または負
}}
**演習3 [#n8dc13ce]
プログラム8を作成し、実行結果を確認せよ。
*配列添字演算子と関数呼び出し演算子 [#n51d4a9c]
配列の添字を表すときに使う角括弧 ''[ ]'' と、関数を呼び出...
|優先順位|演算子|使用例|意味|h
|1|[ ]|a[b]|配列添字|
|~|( )|a(b)|関数呼び出し|
演算子であることを意識する必要はありません。
*演算子の優先順位 [#i79e91b7]
これまでに勉強した演算子の優先順位をまとめておきます。
|優先順位|演算子|使用例|意味|h
|1|[ ]|a[b]|配列添字|
|~|( )|a(b)|関数呼び出し|
|2|+|+a|正の数|
|~|−|−a|負の数|
|~|!|!a|論理否定|
|~|++|i++|値を1増やす|
|~|~|++i|~|
|~|−−|i−−|値を1減らす|
|~|~|−−i|~|
|~|˜|˜a|補数|
|3|()|(b) a|キャスト|
|4|*|a * b|積|
|~|/|a / b|商|
|~|%|a % b|剰余|
|5|+|a + b|和|
|~|−|a − b|差|
|6|<<|a << b|左シフト|
|~|>>|a >> b|右シフト|
|7|<|a < b|小さい|
|~|<=|a <= b|小さいか等しい|
|~|>|a > b|大きい|
|~|>=|a >= b|大きいか等しい|
|8|==|a == b|等しい|
|~|!=|a != b|等しくない|
|9|&|a & b|ビット論理積|
|10|^|a ^ b|ビット排他的論理和|
|11|||a | b|ビット論理和|
|12|&&|a && b|論理積|
|13||||a || b|論理和|
|14|?と:|a ? b : c|条件|
|15|=|a = b|代入|
|~|+=|a += b|加算代入|
|~|−=|a −= b|減算代入|
|~|*=|a *= b|乗算代入|
|~|/=|a /= b|除算代入|
|~|<<=|a <<= b|左シフト代入|
|~|>>=|a >>= b|右シフト代入|
|~|&=|a &= b|ビット論理積代入|
|~|^=|a ^= b|ビット排他的論理和代入|
|~||=|a |= b|ビット論理和代入|
*その他の演算子(おまけ) [#g6a22182]
上の表にない演算子は、C言語応用で勉強する構造体、ポインタ...
|優先順位|演算子|使用例|意味|h
|1|.|a.b|構造体の要素選択|
|2|->|a->b|構造体ポインターの要素選択|
|~|*|*a|ポインター参照|
|~|&|&a|アドレスへのアクセス|
|16|,|a, b|順次|
この他には演算子はありません。
*2進数のビット列を作る(おまけ) [#gacf2a53]
C言語では、16進数では出力できますが、2進数では出力できま...
そこで、2進数のビット列を表す文字列を作成するプログラムを...
ここでは、対象を8ビットの文字としています(プログラム9)。
#geshi(c){{
char c = 'A';
char s[9];
int i;
for (i = 0; i < 8; i++) {
int k = (c >> i) & 0x01; // iビット右にシフトさせて...
s[8 - i - 1] = '0' + k; // 要素番号 8 - i - 1 の要素...
}
s[8] = '\0'; // 文字列の最後にナル文字を代入する
printf("%s\n", s);
}}
#geshi(sh){{
luna% a.out
01000001
}}
*負の符号付き整数をシフト演算で2倍や1/2倍する(おまけ) [...
負の符号付き整数をシフト演算で2倍や1/2倍するには、先頭ビ...
#geshi(c){{
/*
* 先頭ビットが1なら、2の補数の絶対値を求め、1ビット右シ...
* 先頭ビットが0なら、1ビット右シフトして返す。
*/
int half(int x) {
return x >> 31 ? ~(~(x - 0x00000001) >> 1) + 0x00000001...
}
int main(void) {
int i = 0x80000010; // 1000 0000 0000 0000 0000 0000 0...
printf("%08x\n", i);
printf("%d\n", i);
int j = half(i);
printf("%08x\n", j);
printf("%d\n", j);
return 0;
}
}}
#geshi(sh){{
80000010
-2147483632
c0000008
-1073741816
}}
2の補数から絶対値を求める方法や2の補数を求める方法は計算...
終了行:
これまでの勉強で、演算子は必要に応じて少しずつ出てきまし...
ここでは、演算子について、まだ説明していない部分を説明し...
*オペランド [#m77529e0]
演算の対象となる値や変数を''オペランド''といいます。
オペランドが1つの演算子を''単項演算子''、2つのものを''2項...
*増分・減分演算子の前置と後置 [#a54f1eaf]
単項演算子である増分演算子 ''++'' は、オペランドの値を1増...
同じく単項演算子である減分演算子 ''--'' は、オペランドの...
増分・減分演算子は、演算子をオペランドの前に置くこと(前...
''前置''のとき、増分・減分演算子を含む式や命令文は、増分...
''後置''のとき、増分・減分演算子を含む式や命令文は、増分...
次のプログラムは、増分演算子を前置と後置で使用しています...
#geshi(c){{
int i = 0;
printf("%d\n", ++i);
printf("%d\n", i++);
printf("%d\n", i);
}}
最初のprintf関数は、前置の増分演算子なので、先に増分演算...
次のprintf関数は、後置の増分演算子なので、先にprintf関数...
したがって、このプログラムを実行すると、次のようになりま...
#geshi(sh){{
luna% a.out
1
1
2
}}
**演習1 [#e25f652b]
プログラム1を作成し、実行結果を確認せよ。
*ビット単位の演算子 [#jc89f6fc]
データは、すべて2進数のビット列で表されています。
そこで、整数を表す2進数のビット列に対してビット単位で演算...
|優先順位|演算子|使用例|意味|h
|2|˜|˜a|補数|
|6|<<|a << b|左シフト|
|~|>>|a >> b|右シフト|
|9|&|a & b|ビット論理積|
|10|^|a ^ b|ビット排他的論理和|
|11|||a | b|ビット論理和|
補数以外の演算子には、複合代入演算子 <<=, >>=, &=, ^=, |=...
**補数 [#be12c9b2]
補数演算子 ''˜'' は、すべてのビットを反転させます(...
#geshi(c){{
int i = 0x80000010;
int j = ~i
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
7fffffef
}}
**左シフト、右シフト [#u4be1562]
左シフト演算子 ''<<'' はビット列を指定された数だけ左にシ...
1ビット左にシフトするごとに、値は2倍になります。
右シフト演算子 ''>>'' はビット列を指定された数だけ右にシ...
1ビット右にシフトするごとに、値は半分になります。
左オペランドが符号なし整数または符号付き整数で先頭ビット...
左オペランドが符号付き整数で先頭ビットが 1(値が負)のと...
#geshi(c){{
unsigned int ui = 0x00000010;
signed int si = 0x80000010;
printf("%08x, %08x\n", ui, si);
printf("%d, %d\n", ui, si);
ui = ui << 1;
si = si << 1;
printf("%08x, %08x\n", ui, si);
printf("%d, %d\n", ui, si);
}}
#geshi(sh){{
luna% a.out
00000010, 80000010
16, -2147483632
00000020, 00000020
32, 32
}}
**論理積 [#i62e1f15]
ビット単位の論理積演算子 ''&'' は、ビットごとに論理積を取...
論理演算子の論理積演算子 ''&&'' と間違えないよう注意しま...
1 と論理積を取るとそのビットは保存され、0 と論理積をとる...
この性質を利用して、上位ビットや下位ビットだけを取り出す...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i & 0x0000ff;
printf("%08x\n", j);
}}
**論理和 [#y37b82de]
ビット単位の論理和演算子 ''|'' は、ビットごとに論理和を取...
論理演算子の論理和演算子 ''||'' と間違えないよう注意しま...
1 と論理和をとるとそのビットは 1 になり、0 と論理話をとる...
この性質を利用して、特定のビットだけを1にする操作に用いら...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i | 0x0000ff;
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
aaaaaaaa
aaaaaaff
}}
**排他的論理和 [#ja94dc04]
ビット単位の排他的論理和演算子 ''^'' は、ビットごとに排他...
1 と排他的論理和をとるとそのビットは反転し、0 と排他的論...
この性質を利用して、ビット列を部分的に反転させる操作に用...
#geshi(c){{
int i = 0xaaaaaaaa;
printf("%08x\n", i);
int j = i ^ 0x0000ff;
printf("%08x\n", j);
}}
#geshi(sh){{
luna% a.out
aaaaaaaa
aaaaaa55
}}
また、2つ以上のビットの排他的論理和を求めると、ビットに含...
#geshi(c){{
int i = 1 ^ 1 ^ 1 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0;
printf("%d\n", i);
int j = 1 ^ 1 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0;
printf("%d\n", j);
}}
#geshi(sh){{
luna% a.out
1
0
}}
**演習2 [#oab755e9]
プログラム2からプログラム7を作成し、実行結果を確認せよ。
*論理演算子の短絡評価 [#ff7a051e]
論理演算子の論理積 ''&&'' は、いずれかが偽 (0) のときは結...
そこで、論理積演算子は、左側のオペランドを先に評価し、結...
同様に、論理演算子の論理和 ''||'' は、いずれか...
そこで、論理和演算子は、左側のオペランドを先に評価し、結...
これを、論理演算子の''短絡評価''といいます。
この性質を利用して、除算を行う前に割る数が 0 でないことを...
#geshi(c){{
int i = 0;
(i > 0) && printf("正\n");
(i > 0) || printf("0または負\n");
}}
#geshi(sh){{
luna% a.out
0または負
}}
**演習3 [#n8dc13ce]
プログラム8を作成し、実行結果を確認せよ。
*配列添字演算子と関数呼び出し演算子 [#n51d4a9c]
配列の添字を表すときに使う角括弧 ''[ ]'' と、関数を呼び出...
|優先順位|演算子|使用例|意味|h
|1|[ ]|a[b]|配列添字|
|~|( )|a(b)|関数呼び出し|
演算子であることを意識する必要はありません。
*演算子の優先順位 [#i79e91b7]
これまでに勉強した演算子の優先順位をまとめておきます。
|優先順位|演算子|使用例|意味|h
|1|[ ]|a[b]|配列添字|
|~|( )|a(b)|関数呼び出し|
|2|+|+a|正の数|
|~|−|−a|負の数|
|~|!|!a|論理否定|
|~|++|i++|値を1増やす|
|~|~|++i|~|
|~|−−|i−−|値を1減らす|
|~|~|−−i|~|
|~|˜|˜a|補数|
|3|()|(b) a|キャスト|
|4|*|a * b|積|
|~|/|a / b|商|
|~|%|a % b|剰余|
|5|+|a + b|和|
|~|−|a − b|差|
|6|<<|a << b|左シフト|
|~|>>|a >> b|右シフト|
|7|<|a < b|小さい|
|~|<=|a <= b|小さいか等しい|
|~|>|a > b|大きい|
|~|>=|a >= b|大きいか等しい|
|8|==|a == b|等しい|
|~|!=|a != b|等しくない|
|9|&|a & b|ビット論理積|
|10|^|a ^ b|ビット排他的論理和|
|11|||a | b|ビット論理和|
|12|&&|a && b|論理積|
|13||||a || b|論理和|
|14|?と:|a ? b : c|条件|
|15|=|a = b|代入|
|~|+=|a += b|加算代入|
|~|−=|a −= b|減算代入|
|~|*=|a *= b|乗算代入|
|~|/=|a /= b|除算代入|
|~|<<=|a <<= b|左シフト代入|
|~|>>=|a >>= b|右シフト代入|
|~|&=|a &= b|ビット論理積代入|
|~|^=|a ^= b|ビット排他的論理和代入|
|~||=|a |= b|ビット論理和代入|
*その他の演算子(おまけ) [#g6a22182]
上の表にない演算子は、C言語応用で勉強する構造体、ポインタ...
|優先順位|演算子|使用例|意味|h
|1|.|a.b|構造体の要素選択|
|2|->|a->b|構造体ポインターの要素選択|
|~|*|*a|ポインター参照|
|~|&|&a|アドレスへのアクセス|
|16|,|a, b|順次|
この他には演算子はありません。
*2進数のビット列を作る(おまけ) [#gacf2a53]
C言語では、16進数では出力できますが、2進数では出力できま...
そこで、2進数のビット列を表す文字列を作成するプログラムを...
ここでは、対象を8ビットの文字としています(プログラム9)。
#geshi(c){{
char c = 'A';
char s[9];
int i;
for (i = 0; i < 8; i++) {
int k = (c >> i) & 0x01; // iビット右にシフトさせて...
s[8 - i - 1] = '0' + k; // 要素番号 8 - i - 1 の要素...
}
s[8] = '\0'; // 文字列の最後にナル文字を代入する
printf("%s\n", s);
}}
#geshi(sh){{
luna% a.out
01000001
}}
*負の符号付き整数をシフト演算で2倍や1/2倍する(おまけ) [...
負の符号付き整数をシフト演算で2倍や1/2倍するには、先頭ビ...
#geshi(c){{
/*
* 先頭ビットが1なら、2の補数の絶対値を求め、1ビット右シ...
* 先頭ビットが0なら、1ビット右シフトして返す。
*/
int half(int x) {
return x >> 31 ? ~(~(x - 0x00000001) >> 1) + 0x00000001...
}
int main(void) {
int i = 0x80000010; // 1000 0000 0000 0000 0000 0000 0...
printf("%08x\n", i);
printf("%d\n", i);
int j = half(i);
printf("%08x\n", j);
printf("%d\n", j);
return 0;
}
}}
#geshi(sh){{
80000010
-2147483632
c0000008
-1073741816
}}
2の補数から絶対値を求める方法や2の補数を求める方法は計算...
ページ名: