構文の意味を教えてください

[戻る]
1年生 2015/05/24(日) 17:14:00
MFCです。初心者です。独学でやっています。

リストビューで、行単位で色を付けようとしています。
検索したら、このページがありました。
http://www.rakuchinn.jp/programming/mfc_0005.html

その通りやったらうまくいきました。
ただ、構文の意味が解っていません。
13行目です。
m_Flag = m_ctrlList.GetItemState((int)lpnmcd->nmcd.dwItemSpec, LVIS_SELECTED) !
= 0;
最後のところの「!= 0」の意味が解りません。
イコールが2カ所あるのが???です。

どうぞ教えてください。よろしくお願いいたします。

仲澤@失業者 2015/05/25(月) 10:41:23
意気込みは十分わかるのですが、この様な基本的な部分で躓いているようでは先が思いや
られます。
つまり、学習の手順に誤りがある可能性があります。
これを機会に、C/C++言語の入門書ないし、入門サイト等で十分に学んでから先に進む方
が良いかもしれません。

さて、それは置いといて、C/C++言語には「演算子」というものがあります。
「!=」は「比較演算子」と呼ばれ、「(論理的な)真」又は「(論理的な)偽」を戻します。
「比較演算子」には以下の種類があります。

比較演算子    例    意味
<              a < b    (ご自分で調べてみてください)
<=             a <= b   (ご自分で調べてみてください)
>              a > b    (ご自分で調べてみてください)
>=             a >= b   (ご自分で調べてみてください)
==             a == b   aとbが等しい場合に「真」を戻します。そうでない場合に「偽
」を戻します。
!=             a != b   aとbが異なる場合に「真」を戻します。そうでない場合に「偽
」を戻します。

一般的に、「論理的な真」は数値表現では1、「論理的な偽」は0になります。
バージョンの新しいコンパイラではそれぞれ true、falseと書けます。
さらに、Windows上ではそれぞれ TRUE、FALSEと表現される場合がほとんどです。
が、これらは言語の既定ではなく単なる#defineにすぎません。
つまり、これは数値上の1、0の意味合いというわけですね。
もちろん論理的真偽と可換性はあります。


この他、演算子には、「論理演算子」「ビット演算子」など多数の種類があり、
単なる加算に使う「+」も「算術演算子」の一種です。
なんとなく使うのではなく「演算子」を使っているという意識を持って書いてみてはどう
でしょう。

1年生 2015/05/25(月) 16:11:51
仲澤@失業者様 ご親切に有り難うございます。
質問の仕方がよくなかったと思います。
比較演算子自体は理解しているつもりです。

参照したWEBページの13行目が
m_Flag = m_ctrlList.GetItemState((int)lpnmcd->nmcd.dwItemSpec, LVIS_SELECTED);
までであれば、意味は「リストビューの目的の行(アイテム)が選択されていれば
m_Flag に1を代入する(フラッグが立つ)」と理解できるのですが、その先に「!= 0」
が付いている意味が解らないのです。
「!= 0」は不要ではないかと思うのですが・・・
よろしくお願いいたします。

瀬戸っぷ 2015/05/26(火) 17:55:48
>参照したWEBページの13行目が
>m_Flag = m_ctrlList.GetItemState((int)lpnmcd->nmcd.dwItemSpec, LVIS_SELECTED);
>までであれば、意味は「リストビューの目的の行(アイテム)が選択されていれば
>m_Flag に1を代入する(フラッグが立つ)」と理解できるのですが、その先に「!= 0」
>が付いている意味が解らないのです。

型が違うから…では?
GetItemState()の戻り値はUINT。
https://msdn.microsoft.com/ja-jp/library/8zc6atfw.aspx

一方、m_FlagはBOOL型です。
暗黙の型変換で処理するには微妙な関係…かと。
比較演算子の結果であれば、BOOL型への暗黙の型変換でも許容範囲…かと。

ということで……

>「!= 0」は不要ではないかと思うのですが・・・

無いとUINTをBOOLに格納することになります。(ワーニングレベルによっては何かしら出
力されるかと)
あった場合は比較演算子の結果をBOOL型に格納することになります。(0か非0のどちらか)
FALSEは0になると思いますが。
# TRUEは!FALSEで、1である保証はなかった…と思いましたが…違ったかな……。

仲澤@失業者 2015/05/27(水) 11:11:07
瀬戸っぷさんの補足になりますが、まず

 m_Flag はBOOLの可能性がある。

もあり得ますが、bool型の可能性が高いと感じました。まず、BOOLの場合

1.GetItemState()はUINTを戻しますが。m_FlagがBOOL型の場合、これはint なので、
 それを直接代入すると警告される。

は、ありえると思います。次に != 0 部分を省略すると

2.LVIS_SELECTEDは0x0002なので、選択されている場合はGetItemState()は
 2 を戻します。 判定の行 if(m_flag) はm_flagが2でも「真」となりますが、
 もしif(m_flag==TRUE)と書くと結果は「偽」となります。

m_Flag は意味的に「選択されているかどうかの真偽」を表すはずなので
このようにコードしているのだと考えられます。
m_Flag がBOOLの場合厳密には

m_Flag = BOOL( m_ctrlList.GetItemState(・・・) != 0);

と書かなければなりません。
ただし、m_Flagがboolの場合は現在コードでOKといえます。

1年生 2015/05/27(水) 16:37:46
自分の開発環境は Visual Studio 2010 で、コンパイルの警告レベルは実用上一番高い
”Level4(/W4)”に設定しています。

BOOL m_Flag; と定義した場合、お尻の「!=0」があってもなくても警告は出ません。

bool m_Flag; の場合は、お尻の「!=0」があれば警告は出ません。
お尻の「!=0」がない場合は『ブール値を 'true' または 'false' に強制的に設定します
 (警告の処理)』と出ます。

(参照したWEBページでは、BOOL m_Flag; と定義し「!=0」も入れてあるので、念を入れ
たコードを示してくれていると受け止めました。)

瀬戸っぷ様、仲澤@失業者様のご説明で、「!=0」の効能は判りました。
ありがとうございました。

自分は、aaa=bbb という代入式の後ろに !=0 という比較演算子が付け加わる構文は初め
てだったのでお訊ねした訳ですが、
bool m_Flag;
m_Flag = m_ctrlList.GetItemState((int)lpnmcd->nmcd.dwItemSpec, LVIS_SELECTED) !
= 0;
というのは、『GetItemState() が返すUINT値は 0 でないとき真(TRUE) だよ』という意
味になるのでしょうか?

瀬戸っぷ 2015/05/27(水) 16:50:31
>自分は、aaa=bbb という代入式の後ろに !=0 という比較演算子が付け加わる構文は初め
>てだったのでお訊ねした訳ですが、

まぁ、私もそういう記述はやりませんが……(ステップ実行とかやりにくくなるし)
そういう記述例は他にもあったりしますので、覚えておいて損はないかと。
例えば……
http://hitorilife.com/fgetc.php
の下の方にある
while(( get_ch = fgetc( stdin )) != EOF ) {
とか。
fgetc()の結果をget_chに格納し、その値がEOFでない場合にループを継続する。という書
き方になります。
# 今回の質問の事例とは順番が違いますけどね。
# 優先順位明確にする為に括弧つき。

>というのは、『GetItemState() が返すUINT値は 0 でないとき真(TRUE) だよ』という意
>味になるのでしょうか?

そうなります。
同時に、『GetItemState() が返すUINT値が 0 のとき偽(FALSE) だよ』でもありますが。

仲澤@失業者 2015/05/27(水) 18:09:15
>自分は、aaa=bbb という代入式の後ろに !=0 という比較演算子が付け加わる構文は初め
>てだったのでお訊ねした訳ですが、

このように誤った解釈をしているのでは無いかと思ってました。
ですので、入門的解説をお読みになった方が良いのではと申し上げたわけです。
演算子には、評価される優先順位が決まってます。注意しましょう。

aaa=bbb!=0;

というようなコードの場合は次のように解釈されます。

aaa=(bbb!=0);

つまり、代入の後ろで比較しているのではなく、比較した結果を代入するわけですね。
代入演算子「=」は、比較演算子「!=」より優先順位が非常に低いわけですね。

1年生 2015/05/28(木) 08:08:07
[[解決]]
> aaa=(bbb!=0);

これでスッキリ理解できました。
すべて氷解です。
瀬戸っぷ様の「型が違うから…では?」も、仲澤@失業者様の「厳密には m_Flag = BOOL
( m_ctrlList.GetItemState(・・・) != 0);」も解りました。

比較演算子は if文や while文で使うと思っていて、代入文に使われているのが初めてだ
ったので面食らいました。

ありがとうございました。

古いスレッドには追加発言できません。