[C言語] Cパズルブック 1.4.7 ビット演算子 ビットXOR ^

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

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

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

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

    // 問1.4.7
    PRINT( x ^ x);   // 0

    // 計算1: x ^ x
    // x = 0b00000001
    // x = 0b00000001
    // ^ --------------
    //     0b00000000  

    // よって10進数0となる

    return 0;
}
0

[C言語] Cパズルブック 1.4.6 ビット演算子 ビット反転演算子~

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

問1.4.6の解法は以下の通りです。符号付き整数型ですからビット番号7(右から8番目)は符号を表します。

計算3で少し手間取りました。

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

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

    // 問1.4.6
    PRINT( ~x | x);   // -1

    // ビット反転演算子~を優先
    PRINT(~x);        // -2
    PRINT( (~x) | x); // -1

    // 計算1: ~x
    // x = 0b00000001
    // ~ --------------
    //     0b11111110     

    // 計算2: (~x) | x
    // Lt = 0b11111110
    // x  = 0b00000001
    // | -------------
    //      0b11111111(符号付き -128から127まで)

    // 計算3:10進数へ変換
    // 0b11111111の最上位ビット(右から8番目)は1なので負数
    // 反転したビットに1を加える
    // 0b00000000 + 1 = 0b00000001 = 10進数1
    // 負数なのでマイナスを付けて10進数-1になる

    return 0;
}
-1
-2
-1

[C言語] Cパズルブック 1.4.4 ビット演算子 論理AND

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

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

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

int main() {
    int x , y, z;
    
    // 先頭に0を付けると8進数になる
    x = 03; y = 02; z = 01;

    // 問1.4.4
    PRINT( x & y && z);   // 1

    // ビットAND &を優先
    PRINT( (x & y) && z); // 1

    // 計算1: x & y
    // x = 0b00000011
    // y = 0b00000010
    // & --------------
    //     0b00000010

    // 計算2: (x & y) && z
    // Lt = 0b00000010 != 0 = TRUE
    // z  = 0b00000001 != 0 = TRUE
    // && -------------
    //      TRUE or 1

    // よってTRUE(10進数1)になる

    return 0;
}
1
1

[C言語] Cパズルブック 1.4.3 ビット演算子 ビットXOR

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

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

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

int main() {
    int x , y, z;
    
    // 先頭に0を付けると8進数になる
    x = 03; y = 02; z = 01;

    // 問1.4.3
    PRINT( x ^ y & ~z);   // 1

    // 補数~,ビット積&を優先
    PRINT( x ^ (y & (~z))); // 1

    // 計算1: ~z(zの補数)
    // z = 0b00000001
    // ~ --------------
    //     0b11111110

    // 計算2: y & ~z
    // y  = 0b00000010
    // ~z = 0b11111110
    // & --------------
    //      0b00000010

    // 計算3: x ^ (y & ~z)
    // x  = 0b00000011
    // Rt = 0b00000010
    // ^ --------------
    //      0b00000001
    // ビットXOR:同じ0,違う1
    // よって10進数1になる

    return 0;
}
1
1

[C言語] Cパズルブック 1.4.2 ビット演算子 ビット補数

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

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

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

int main() {
    int x , y, z;
    
    // 先頭に0を付けると8進数になる
    x = 03; y = 02; z = 01;

    // 問1.4.2
    PRINT( x | y & ~z);   // 3

    // 補数~,ビット積&を優先
    PRINT( x | (y & (~z))); // 3

    // 計算1: ~z(zの補数)
    // z = 0b00000001
    // ~ --------------
    //     0b11111110

    // 計算2: y & ~z
    // y  = 0b00000010
    // ~z = 0b11111110
    // & --------------
    //      0b00000010

    // 計算3: x | (y & ~z)
    // x  = 0b00000011
    // Rt = 0b00000010
    // | --------------
    //      0b00000011
    // よって10進数3になる

    return 0;
}
3
3

[C言語] Cパズルブック 1.4.1 ビット演算子 ビットAND

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

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

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

int main() {
    int x , y, z;
    
    // 先頭に0を付けると8進数になる
    x = 03; y = 02; z = 01;

    // 問1.4.1
    PRINT( x | y & z);   // 3

    // ビットAND &を優先
    PRINT( x | (y & z)); // 3

    // 計算1: y & z
    // y = 0b00000010
    // z = 0b00000001
    // & --------------
    //     0b00000000

    // 計算2: x | 00
    // x  = 0b00000011
    // 00 = 0b00000000
    // | --------------
    //      0b00000011
    // よって10進数3になる

    return 0;
}
3
3

[C言語] Cパズルブック 1.4 ビット演算子 

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

昨年2022年12月以来のCパズルブックです。

コードと出力は以下の通りです。

次回以降、各行について詳説します。

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

int main() {
    int x , y, z, a;
    
    // 先頭に0を付けると8進数になる
    x = 03; y = 02; z = 01; a = 010;

    printf("前半\n");

    PRINT( x | y & z);   // 3
    PRINT( x | y & ~ z); // 3
    PRINT( x ^ y & ~ z); // 1
    PRINT( x & y && z);  // 1

    // 追加
    PRINT( ~ z);         //-2
    PRINT(a);            // 8 8進数になっているか確認

    printf("後半\n");

    x = 1; y = -1;
    PRINT( ! x | x);     // 1
    PRINT( ~ x | x);     //-1
    PRINT( x ^ x);       // 0
    x <<= 3; PRINT(x);   // 8
    y <<= 3; PRINT(y);   //-8
    y >>= 3; PRINT(y);   //-1

    return 0;
}
前半
3
3
1
1
-2
8
後半
1
-1
0
8
-8
-1

[C言語] Cパズルブック 1.3 論理演算子とインクリメント演算子

『Cパズルブック』(Alan R.Feuer, 1985)
[M1 Mac, Big Sur 11.7.2, clang 13.0.0, NO IDE]

3番目以降は難問でした。

最後のz = x / ++ xは優先度3の除算と優先度2の前置インクリメントの関係を厳格に用いると先にインクリメントが実行され後で除算になるので4/4の1になりますが、実際の計算結果は3/4の商である0になります。

この計算式については除算が優先されています。gccもclangも同じ結果でした(コンパイラは一応下記警告を発していました)。本の解答はコンパイラ次第なので ? になっています。

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

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

    x = 2; y = 1; z = 0;
    x = x && y || x;        // (TRUE and TRUE) or TRUE = TRUE 1
    PRINT(x);               // 1
    PRINT(x || ! y && z);   // (TRUE or FALSE) or FALSE = TRUE 1

    x = y = 1;
    z = x ++ -1; // z = 1 - 1 後置インクリメントなのでx++評価後にxが2に増加する
    PRINT(x);   // 2
    PRINT(z);   // 0
    z += - x ++ + ++ y; // 0 + -(2) + 2
    PRINT(x);   // 3
    PRINT(z);   // 0
    z = x / ++ x; // z = 3/4 or 4/4
    PRINT(z);   // 0 or 1

    return 0;
}
src/test.c:19:13: warning: unsequenced modification and access to 'x' [-Wunsequenced]
    z = x / ++ x; // 3 / 4
        ~   ^
1 warning generated.

[C言語] Cパズルブック 1.2 代入演算子

『Cパズルブック』(Alan R.Feuer, 1985)
[M1 Mac, Big Sur 11.7.2, clang 13.0.0, NO IDE]

『Cプログラミングの落とし穴』をようやく読了しました。今後もプログラミングに関する名著を継続して読んでいきます。

次はベル研究所内の教材を元に製作された『Cパズルブック』です。1985年の初版なので記述形式はK&Rスタイルになります。

1.2の3番目はまずy==zで左辺右辺を比較していてイコールが成り立つのでTRUE 1になり、これをxに代入するためPRINTXの出力は1になります。比較演算子==と代入演算子=の使い分けが出題の目的です。

4番目は式自体はx = 1,とy = z = 4の比較でFALSE 0になりますが、xは1のままですから1が出力されます。

第8章までありますが、来年1月中の読了を目指します。これを読み切ったら、以前さらっと目を通しただけのK&R 第2版(ANSI C)に取り組みます。

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

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

    x *= 3 + 2;  // 10
    PRINTX;

    x *= y = z = 4; // 40
    PRINTX;

    x = y == z; // 1
    PRINTX;

    x == ( y = z); // 1
    PRINTX;

    return 0;
}