[C言語] Cパズルブック 1.6 演算子の優先順位とその評価

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, macOS Ventura 13.3.1, clang 14.0.3]

問1.6.1-6の解法は以下の通りです。

プログラミングの学習と言うよりも頭のトレーニング的な感じです。

真偽が確定していれば計算機は作業を止めますが、人間の作業や業務においては無駄な真偽評価をすることが多々あります。モチベーションが下がるだけですね。特に日本人はやりがち。

ようやく第1章が終わりました。次の章をどれにするかは興味本位で決めたいです。

#include <stdio.h>
#define PRINT3(x, y, z) printf("x = %d\ty = %d\tz = %d\n", x, y, z)

int main() {
    int x , y, z;

    // 問1.6.1
    x = y = z = 1;
    ++x || ++y && ++z;
    PRINT3(x, y, z);

    // ++x || (++y && ++z)
    // 計算機は左から評価を行う
    // 計算1: ++xによりx = 2となりTRUE
    // 計算2: ||を読込み、すでに左がTRUEなので計算終了
    // よって、x = 2, y = 1, z = 1

    // 問1.6.2
    x = y = z = 1;
    ++x && ++y || ++z;
    PRINT3(x, y, z);

    // (++x && ++y) || ++z
    // 計算1: ++xによりx = 2となりTRUE
    // 計算2: &&を読込み、++yによりy = 2となりTRUE、左はTRUE
    // 計算3: ||を読込み、すでに左がTRUEなので計算終了
    // よって、x = 2, y = 2, z = 1

    // 問1.6.3
    x = y = z = 1;
    ++x && ++y && ++z;
    PRINT3(x, y, z);

    // (++x && ++y) && ++z
    // 計算1: ++xによりx = 2となりTRUE
    // 計算2: &&を読込み、++yによりy = 2となりTRUE、左はTRUE
    // 計算3: &&を読込み、++zによりz = 2となりTRUE、TRUE && TRUE = TRUE 
    // よって、x = 2, y = 2, z = 2

    // 問1.6.4
    x = y = z = -1;
    ++x && ++y || ++z;
    PRINT3(x, y, z);

    // (++x && ++y) || ++z
    // 計算1: ++xによりx = 0となりFALSE 左はFALSE確定のため++yは評価しない
    // 計算2: ||を読込み、左がFALSEなので次に進む
    // 計算3: ++zによりz = 0となりFALSE、FALSE || FALSE = FALSE
    // よって、x = 0, y = -1, z = 0

    // 問1.6.5
    x = y = z = -1;
    ++x || ++y && ++z;
    PRINT3(x, y, z);

    // ++x || (++y && ++z)
    // 計算1: ++xによりx = 0となりFALSE
    // 計算2: ||を読込み、左がFALSEなので次に進む
    // 計算3: ++yによりy = 0となりFALSE、&&を読込み右はFALSE確定のため++Zは評価しない
    // 計算4: FALSE || FALSE = FALSE
    // よって、x = 0, y = 0, z = -1

    // 問1.6.6
    x = y = z = -1;
    ++x && ++y && ++z;
    PRINT3(x, y, z);

    // (++x && ++y) && ++z
    // 計算1: ++xによりx = 0となりFALSE
    // 計算2: &&を読込み、左はFALSEのためFALSE確定。++yは評価しない
    // 計算3: &&を読込み、左はFALSEのためFALSE確定。++zは評価しない
    // 計算4: FALSE && FALSE = FALSE
    // よって、x = 0, y = -1, z = -1

    return 0;
}
x = 2	y = 1	z = 1
x = 2	y = 2	z = 1
x = 2	y = 2	z = 2
x = 0	y = -1	z = 0
x = 0	y = 0	z = -1
x = 0	y = -1	z = -1

[C言語] Cパズルブック 1.5.4-5 関係演算子と条件演算子 3値の比較

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, macOS Ventura 13.3.1, clang 14.0.3]

問1.5.4 -5の解法は以下の通りです。

#include <stdio.h>
#define PRINT(int) printf("%d\n",int)

int main() {
    int x , y, z;

    x = 3; y = z = 4;

    // 問1.5.4
    PRINT((z >= y >= x) ? 1 : 0);

    // PRINT(((z >= y) >= x) ? 1 : 0);
    // 計算1: z >= y
    //       4 >= 4 はTRUE 1
    // 計算2: (z >= y) >= x
    //       1 >= 3 はFALSE
    // 計算3: Lt ? 1 : 0
    //       FALSEは0
    // よって出力は0となる
    // しかし途中で整数がブール値に変わっていて正しい比較になっていない

    // 問1.5.5
    PRINT(z >= y && y >= x);

    // PRINT((z >= y) && (y >= x));
    // 計算1: z >= y
    //       4 >= 4 はTRUE 1
    // 計算2: y >= x
    //       4 >= 3 はTRUE 1
    // 計算3: Lt && Rt
    //       TRUE && TRUEは1
    // よって出力は1となる
    // こちらはブール値の論理ANDを計算する形でありx,y,zの正しい比較になっている

    return 0;
}
0
1

[C言語] Cパズルブック 1.5.3 関係演算子と条件演算子 加算代入演算子 +=

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, MacOS Ventura 13.3.1, clang 14.0.3]

問1.5.3の解法は以下の通りです。

パズルなので楽しめていますが、実務でそのまま使うのは顰蹙ものでしょうか。せめて括弧で補足したいところです。

#include <stdio.h>
#define PRINT(int) printf("%d\n",int)

int main() {
    int x , y, z;

    x = 3; y = 3; z = 1;
    
    PRINT(z += x < y ? x++ : y++);
    PRINT(y); PRINT(z);

    // PRINT(z += (x < y ? x++ : y++));

    // 計算1: x < y
    //       3 < 3 は FALSE
    // 計算2: x < y ? x++ : y++
    //       FALSEはy++
    //       y++は評価時はまだ加算しないため3のまま
    // 計算3: z += Rt
    //       z = z + Rt = 1 + 3 = 4

    // 計算4: y
    //       y++評価後は1増えるので4になる
    // 計算5: z = 4
    
    // よって出力は4, 4, 4となる

    return 0;
}
4
4
4

[C言語] Cパズルブック 1.5.2 関係演算子と条件演算子 後置インクリメント x++

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, MacOS Ventura 13.3.1, clang 14.0.3]

問1.5.2の解法は以下の通りです。

#include <stdio.h>
#define PRINT(int) printf("%d\n",int)

int main() {
    int x , y, z;
    
    x = 1; y = 1; z = 1;

    x += y += z;

    PRINT(x < y ? x++ : y++);
    PRINT(x); PRINT(y);

    // x = 3; y = 2; z = 1;
    // 計算1: x < y
    //       3 < 2 は FALSE
    // 計算2: x < y ? x++ : y++
    //       FALSEはy++
    //       y++は評価時はまだ加算しないため2のまま

    // 計算3: x
    //       x++は評価されなかったので3のまま
    // 計算4: y
    //       y++評価後は1増えるので3になる
    
    // よって出力は2, 3, 3となる

    return 0;
}
2
3
3

[C言語] Cパズルブック 1.5.1 関係演算子と条件演算子 三項演算子 x ? y : z

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, MacOS Ventura 13.3.1, clang 14.0.3]

問1.5.1の解法は以下の通りです。

#include <stdio.h>
#define PRINT(int) printf("%d\n",int)

int main() {
    int x , y, z;
    
    x = 1; y = 1; z = 1;

    x += y += z;
    PRINT(x < y ? y : x);

    PRINT((x < y) ? y : x);

    // x += (y += z)
    // 計算1: y += z
    //       y = y + z = 2
    // 計算2: x += (y += z)
    //       x = x + Rt = 1 + 2 = 3      

    // (x < y) ? y : x
    // 計算3: x < y
    //       3 < 2 は FALSE
    // 計算4: (x < y) ? y : x
    //       FALSEはx
    
    // よって出力は3となる

    return 0;
}
3
3

[C言語] Cパズルブック 1.5 関係演算子と条件演算子

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, MacOS Ventura 13.3.1, clang 14.0.3]

Cパズルブック 1.5のコードおよび出力は以下の通りです。

次回以降で各問解答について詳説します。

#include <stdio.h>
#define PRINT(int) printf("%d\n",int)

int main() {
    int x , y, z;
    
    x = 1; y = 1; z = 1;

    x += y += z;
    PRINT(x < y ? y : x);

    PRINT(x < y ? x++ : y++);
    PRINT(x); PRINT(y);

    PRINT(z += x< y ? x++ : y++);
    PRINT(y); PRINT(z);

    x = 3; y = z = 4;
    PRINT((z >= y >= x) ? 1 : 0);
    PRINT( z >= y && y >= x);

    return 0;
}
3
2
3
3
4
4
4
0
1