C言語の記述について

お世話になっております。いいよぉです。素人的な質問となりますが、下記わかればご教示ください。

 

条件式Aと条件式Bとの積を通常「&&」で取っていますが、不意に記述ミスで「&」で記述している部分があったのですが、

ABの条件を4通りふって検証したところ、問題なく判定されておりました。

 

if((条件文A)&(条件文B))・・・・は、 if((条件文A)&&(条件文B)) と同じ判定になりました。

 

・記述する条件分によって、同じ意味を持つのでしょうか。

・できるケースとできないケースとがありますでしょうか。

・コンパイラによって、正式な&&へ修正されているのでしょうか。

以上、宜しくお願い致します。

  • if((条件文A)&(条件文B)) は 条件文A の結果と条件文B の結果の論理積を取るので 条件文A と 条件文B は常に評価されます。
    if((条件文A)&&(条件文B)) では 条件文A が偽だった場合、条件文B は評価されません。
  • わわいです
    演算子 && というのは、論理式の AND で、
    演算子 & はビットごとのAND となります

    >・記述する条件分によって、同じ意味を持つのでしょうか。
    あなたの示している条件式では双方同じ結果となります

    >・できるケースとできないケースとがありますでしょうか。
    a=1; b=2;
    の場合では、 a && b は1となりますが、
    a&b の場合は0となってしまいますね

    >・コンパイラによって、正式な&&へ修正されているのでしょうか。
    されません
  • 補足になります。


    具体的な条件文AとBの記述が無いので、例えば、

    a=0;
    b=1;
    c=2;
    d=3;
    e=4;
    if((a>b)&(c==(d=e))){}

    のとき、if文実行後にdは4になりますが、

    a=0;
    b=1;
    c=2;
    d=3;
    e=4;
    if((a>b)&&(c==(d=e))){}

    のときにはdは3になります。

    #define LENGTH 10
    char a[LENGTH];
    int i;
    char c;
    ・・・・・
    if((LENGTH>i)&(c==(a[i]=getch()))){}
    ・・・・・
    なんてのはやりそうで、見つけにくいバグです。



    多くのコンパイラが準拠しているANSI-Cだと真が“0”以外、偽が“0”です。78K0のC言語マニュアルでは、真が“1”、偽が“0”と書かれてます。型変換した際に思わぬビットがセットされることがあるので要注意です。
  • kijoさん

    ほやです。

    > 多くのコンパイラが準拠しているANSI-Cだと真が“0”以外、偽が“0”です。78K0のC言語マニュアルでは、真が“1”、偽が“0”と書かれてます。
    処理系によっては、真= -1 で実装しているものもあります。
    しかしunsignedで扱うと 真= -1 では 0xff や0xffffに変換されたりして値が一致しなくなってしまうため、組み込みプログラムでは 真 = 1 で実装されている方が何かと都合が良いのではないかと思ったりします。

    とは言えプログラムを記述する際には特定の値が入るのを期待するのでなく、ANSI規格通り 「0か、0以外か」 で判別するように組むのが無難でしょうね。

    ちなみによくあるミスで、if文に == (比較) と間違えて = (代入) を入れてしまうと、非常に分かりにくいバグが出来上がります。比較演算子の左辺には代入できない値(定数やconst)を置くように常に習慣付けておくと、こういうミスは防止できる... と大昔に習いました。

    > if((LENGTH>i)&(c==(a[i]=getch()))){}
    こういうのは判定結果を一時変数に取っておいてから処理する書き方に変える事をお勧めしたいです。
    冗長に見えるかもしれませんが、いまどきのコンパイラは一時変数を使わないコードに置き換えてくれますから処理速度やメモリの点でも損は出ないと思います。
  • > 処理系によっては、真= -1 で実装しているものもあります。

    1981年発行の『プログラミング言語C』初版(所謂 K&R)の「7.6 関係演算子」の項に

    演算子 < (より小さい), > (より大きい), <= (小さいか等しい), >= (大きいか等しい)は,指定された関係が成り立たなければ, 答として 0 を出し,正しければ1を出す。結果の型は int であり,通常の算術変換が行われる。

    「7.7 等値演算子」の項には

    == (等しい) と != (等しくない) の演算子は,優先順位が低いことを除けば関係演算子と同じようなものである。(a>b==c<d は a<b と c<d が同じ真理値をとれば 1 となる。)

    「7.11 論理的 AND 演算子」の項には

    && 演算子は左から右へ適用される。これは,両被演算数が非零のとき 1 を返し,そうでなければ 0 を返す。

    「7.12 論理的 OR 演算子」の項には

    || 演算子は左から右へ適用される。これは,どちらかのオペランドが非零であれば 1 を返し,そうでない場合は 0 を返す。

    ANSI 規格化以前の C言語の仕様として 真=1 が明確に書かれており、それ以外の実装が存在するとは俄かには信じがたいのですが 真= -1 の処理系があるというのは事実でしょうか? 具体的な処理系を挙げていただけると嬉しいです。

  • fujitaさん

    C言語以外(VB,PHP,SQL,etc)では ture=-1 は多くありますが、確かにC言語で true=1以外はあまりないですね。

    大昔に使っていた処理系で true = !false (~0 (NOT 0) = -1) として実装していたものがあって、それで痛い目を見ている人が身近にいたので私にはtrueの値を信用しない習慣が染みついています。(考えようによっては true == !false は素直な実装かもしれません)

    ちなみに C# のfalse operatorの実装は false = -1, null =0, true =1 のように、思いもよらない値になっているらしいです。
    (null とfalseを区別しようとしたらそうなったのかな?)
  • if((条件文A)&&(条件文B))

    ここでポイントとなるのが、「条件文」の所です。
    「条件文」と言う事は、「0」か「非0」が入っていると言う事ではないか。
    「非0」がコンパイラの内部処理によって 0x01 0xFF のどちらであっても
    (条件文A) && (条件文B) と (条件文A) & (条件文B) は同じになりますね。
  • fujita nozomu 様

    返信遅れました、適切な回答ありがとうございました。
    下側の文では条件文A が偽だった場合、早めに抜けると捉えました。(条件文A が真だった場合は、同じ処理時間)
    この説明では、同じ結果が出ていたことに納得がいっております。
  • わわい様


    返信遅れました、補足を含めて適切な回答ありがとうございました。

    条件式は、例えると
    if( ((A & 0x03) == 0x03)&(B != C) )
    という式でした。

    前側の結果と後側の結果との論理積を取っていて、結果が同じになっているのだと考えております。
  • リカルド さん

    返信遅れました、適切な回答ありがとうございました。

    条件式は、例えると
    if( ((A & 0x03) == 0x03)&(B != C) )
    という式でした。

    マイコンは78K0Rに実装しております。
    前側の結果(1or0)と後側の結果(1or0)との論理積を取っていて、結果が同じになっているのだと考えております。