#pragma twice

KAB-studio > プログラミング > #pragma twice > 109 Version 6.09 単項演算子

#pragma twice 109 Version 6.09 単項演算子

前のページへ 表紙・目次へ 次のページへ

 Version 6.09
単項演算子

さて今回から、バグの出やすい部分や見つけ方とかを具体的に紹介してい
きます
バグの出やすいとこってあるんだ
あるよー。まずは演算子関係
演算子って、 + とか - とかだよね
そうそう。そういう四則演算から、 << とかのビット演算系、 && とかの
論理演算系、 == や < の比較演算系、って感じに演算子はいっぱいありま

 MSDN で見てみても、かなりの数あるね
そこで、演算子関係のバグを紹介する前に、全部の演算子についてまとめ
ておきます
おお! って、もしかしてあたし、全然演算子のこと教えてもらってな
い?
必要になってから教えてたからね……。ま、今からでも遅くないでしょ
ホントかなー
さて、まず重要なのは、演算子は基本型に使うものってこと
基本型?
 int とか char とか、あとポインタとかの、最初から存在する型のこと
を〈基本型〉とか〈プリミティブ型〉とかいいます
つまりクラスじゃない型ってこと?
そういうこと! 基本的に、クラスには演算子を使えません

void CDebugDlg::OnButton1() 
{
    CWnd cWnd;
    cWnd = 100;
}

あ、コンパイルエラーになった
ただ、クラスの中には演算子を使えるようにしてあるものもあります

void CDebugDlg::OnButton1() 
{
    CString cStr;
    cStr = "あいうえお";
}

ちょっとややこしいかも
 MFC のクラスなら、 MSDN で CString のメンバ関数を見てみると、
operator = とかあるでしょ。これが〈 = 演算子は使えるよ〉って意味
でもまだ難しい……
ま、今回はクラスの話じゃないからこれは置いといて。では早速、演算子
について見ていきましょう。 MSDN の【 C++ 演算子】ってページを開いて
あ、さっき見つけたページだ。いっぱいあるよねー
まー数はあるけど、実際はそんなに多いって感じないと思うよ。まず、使
い方別に見ていくね。 MSDN の【単項演算子】−【 C++ 単項演算子】を選
んで
ほい。 ! とか & とか出てきた
全部並べると、 ! & ~ * + - ++ -- 
最初の ! は if の中で使うのだね。反対にするヤツ
そう、 ! はゼロを 0 以外に、 0 以外をゼロにします
 & は……あれ? これって、アドレス出すの? それともビットで両方
とも 1 だったら 1 になるっての?
これは、アドレスの方の。ここに出てる演算子って〈単項演算子〉って
なってるでしょ。単項演算子っていうのは……〈オペランド〉って憶えて
る?
もちろん。 2 + 3 なら、 2 が左オペランドで、 3 が右オペランドで
しょ
こういう、左右にオペランドがくっつくのを【二項演算子】っていいま
す。オペランドの事を〈項〉って言うからね。ってことは?
単項演算子は、オペランドがいっこってこと?
そういうこと! だから、 & 変数が1個だけ付いてたら単項演算子、2
個付いてたら二項演算子として機能するわけ
二項か単項かって、どう見分けるの? あ! 二項は変数にくっつけない
で、単項はくっつけるんだ!
ぶっぶー。単項演算子は変数と離してても機能します

void CDebugDlg::OnButton1() 
{
    int i = 0;
    TRACE( "%X\n", &                   i );
}

これでアドレスがちゃんと出るんだ……
それに、二項演算子で変数とくっつけないのは僕のスタイル。くっつけて
る人は結構いるよ?
そういえば……
単項演算子か二項演算子かっていうのは、演算子掛けたあとは値になる、
ってことを憶えとけば大丈夫だと思うよ
値になる、って、たとえばさっきの ! だと 0 とか 0 以外になるとかっ
て意味?
そうそう、 & ならアドレスになるし、 ++ なら1増えた値だし。これは
二項演算子にも言えることでしょ
そういえば、 a + b はその足したのに置き換わる、って前にやったね
 Ver 2.4 ( No.015 ) だね。かなり昔……
この〈置き換わる〉って、 typedef とかに似てるね
それは結構重要なこと
おお
でも難しいから、詳しくはもう少し先になってから
あら
話を元に戻すと、さっきの火美ちゃんの例に似た形で言えば

    a & b

は、もし & を単項演算子にしちゃうと
 & b が値に置き換わっちゃう
変数や値が、演算子ナシに並ぶのはダメだからこれはあり得ない、だから
コンパイルするときに & は二項演算子だ、って扱われるわけ
でもさ、これは?

    a & &b

単項演算子は右側の変数にしかくっつかないからね。真ん中の & は a に
付かないでしょ
単項演算子は右側の変数にしか付かない、ね
あ、後置の ++ と -- は別だからね
次の行に行く前に増えたり減ったりってヤツね。そういえばあれは変数の
右側に付けるよね
ま、あれは特別。単項演算子は右にくっつく、って憶えとけばOK
ようするに、矛盾がなければそう見られるってことでしょ?
まぁね。単項演算子で分かんないのある?
 ~ は教えてもらってないかな。 MSDN 見ると〈1の補数〉って書いてあ
るけど、何それ。歩数1? 1歩前へ?
補数っていうのは、普通の10進数の数で言うと、足して9とか99とか
にする数字。7を9にするには?
2足せば9
ってことは7の補数は2てこと。こういう〈補う数〉を〈補数〉って言う
わけ。簡単に言えばね
その補数を作るのが ~ ってことなんだ……あれ?

    TRACE( "%d\n", ~7 );  // -8

ウソツキ!! なにが足して9になる数よ!!
違う違う! ~ は10進数じゃなくて、2進数での補数を作る演算子な
の!
2進数?
そう。 0x77777777 を例にしてみようか。10進数の9、つまり〈次の桁
に移る直前の数〉は、16進数だと?
15。ってことは、7引くと8だね
ってことで

    TRACE( "%X\n", ~0x77777777 );
    // 88888888

お、ホントだ
でしょう
……んな勝ち誇った顔はいいから、これが何の役に立つの?
そこが重要。とりあえず、今言った〈補う数〉とかっていうのは忘れてい
いから
えええ??
16進数の 7 をビットで表すと?
 0111 だよ
じゃあ 8 は?
 1000 ……って、水希ちゃんバカにしてる?
同じく、 5 について

    TRACE( "%X\n", ~0x55555555 );
    // AAAAAAAA

 5 は 0101 、 A は 1010 だよ
さて問題。ビットで表すと、普通の数と補数の関係は?
えーっと……あ!
そう、ビットが反転してるでしょ
なに? つまりようするに ~ はビット反転するための演算子ってこ
と?
そういうこと。補数とか難しいこといってるけど、基本的にはこれだけの
こと
じゃー初めからそういえばいいじゃん。うー
まーそうなんだけどね
で、これって何に使うの?
一番よく使うのは、ビットフラグを取り除くときかな。 Ver 5.24 
( No.089 )
 でやったウィンドウスタイルの話を思い出して
ウィンドウの形とかが、ビットフラグで入ってるんだよね。 
CWnd::GetStyle() とか使って調べられて
セットされてるスタイルから、あるひとつのスタイルだけ取り除く場合、
まずウィンドウスタイルを取得して、取り除くスタイルのビットを取り除い
て、再びセットしなおします
それに ~ を使うの?
そゆこと。たとえば 0101 から 0001 ビットを取り除きたい場合

    int iModified
        = 0x00000005 & ~0x00000001;

    TRACE( "%X\n", iModified );
    // 4

なんかややこしい……と、ひとつずつ見てけ?
そゆこと
 0x00000001 が 0001 、これを反転するから 1110 。で、 0101 と & す
るわけだから…… & って各ビットで、両方とも 1 のときだけ 1 だよね
そ。 4.05 ( No.055 ) を読み返してみて
だから、 0101 & 1110 で……ホントだ、 0100 で 0001 が取り除けた
 ~ で反転すれば、 0001 が 1110 になったみたく、立ってたビットだけ
が 0 に、他は 1 でしょ
当たり前じゃない
それに & すれば、立ってたビットは絶対に 0 になるから
そっか、それで絶対に消せるんだ
他のビットは、 1 のとこはそのまま 1 、 0 もそのまま 0 
ほー、良くできてるね〜。これが ~ の使い道ってわけだ
ってゆーか、実際にはこっちから見ていった方が分かりやすいかな
どゆこと?
つまり、まず〈ビットフラグを取り除く〉って目的から入って、それには
~ を使う、ってこと
それが〈必要になったら教える〉ってことね
プログラミングに使うものって、色々使えそうで、実はほんの少しのこと
にしか使われてないことって多いからね
あと単項演算子で知らないのは…… + と - は?
まんま、プラスとマイナス。正の数と負の数を作るためのもの
じゃ、単項演算子は全部分かったかな
では次回は二項演算子について見ていきましょう!

/*
    Preview Next Story!
*/
ねー、単項演算子の + って何に使うの?
特に使い道ないんじゃないかな、たぶん
たぶん?
う”、演算子って実はこういう使い方ができる、とかあるからねぇ
水希ちゃんでも知らないことってあるのねー
というわけで次回
< Version 6.10 二項演算子 >
につづく!
でも、やっぱり使い道はないんじゃないかな
ホント?
う”……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。