Open5

C

nicopinnicopin

memcpy

void *memcpy(void *dest, const void *src, size_t n);
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

int main(void) {
    printf("char : %lu\n", sizeof(char));
    printf("short int : %lu\n", sizeof(short int));
    printf("int : %lu\n", sizeof(int));
    printf("long int : %lu\n", sizeof(long int));
    printf("float : %lu\n", sizeof(float));
    printf("double : %lu\n", sizeof(double));
    printf("long double : %lu\n", sizeof(long double));
    printf("bool : %lu\n", sizeof(bool));

    bool bits[8] = {true, true, true, true, true, true, false, false,};
    bool twoBits[2];
    //配列をそのまま使用すると先頭のポインタが渡される
    memcpy(twoBits, bits, 2);
    printf("twoBits[0] : %d\n", twoBits[0]);
    printf("twoBits[1] : %d\n", twoBits[1]);

    bool twoLastBits[2];
    //memcpyの第二引数はポインタ型なので&をつける
    memcpy(twoLastBits, &bits[6], 2);
    printf("twoLastBits[0] : %d\n", twoLastBits[0]);
    printf("twoLastBits[1] : %d\n", twoLastBits[1]);

    int bitsInt[8] = {1, 1, 1, 1, 1, 1, 1, 1,};
    int twoBitsInt[2];
    //サイズはバイト数なのでint型のサイズに合わせて指定する
    memcpy(twoBitsInt, bitsInt, 2 * sizeof(int));
    printf("twoBitsInt[0] : %d\n", twoBitsInt[0]);
    printf("twoBitsInt[1] : %d\n", twoBitsInt[1]);

    return 0;
}
/*-----------------------*/
//char : 1
//short int : 2
//int : 4
//long int : 8
//float : 4
//double : 8
//long double : 8
//bool : 1
//twoBits[0] : 1
//twoBits[1] : 1
//twoLastBits[0] : 0
//twoLastBits[1] : 0
//twoBitsInt[0] : 1
//twoBitsInt[1] : 1
nicopinnicopin

ビットシフト

ビットシフトとは、デジタルコンピューティングにおいて、整数内のビット(0と1)を左または右に移動させる操作のことです。ビットシフトには主に2種類があります:

左シフト(Left Shift):

<< 演算子を使用します。
指定された数だけビットを左に移動させます。
左端からはみ出したビットは失われ、右端には0が挿入されます。
数値を2のべき乗で増加させる効果があります。たとえば、1 << 1 は1を2倍にします。
例:
数値 2 はバイナリで 10 です。2 << 1 を行うと、ビットが1つ左にシフトされ 100(バイナリ)となり、これは10進数で 4 です。

右シフト(Right Shift):

>> 演算子を使用します。
指定された数だけビットを右に移動させます。
右端からはみ出したビットは失われ、左端には0または符号ビット(符号付き整数の場合)が挿入されることが一般的です。
数値を2のべき乗で減少させる効果があります。たとえば、4 >> 1 は4を2で割った値です。
例:
数値 4 はバイナリで 100 です。4 >> 1 を行うと、ビットが1つ右にシフトされ 10(バイナリ)となり、これは10進数で 2 です。
ビットシフトは、効率的な計算(特に乗算や除算の代替として)、データのエンコードやデコード、ビットレベルでの操作など、多くのプログラミングタスクで広く使用されます。ビットシフトを利用することで、プログラムのパフォーマンスを向上させることができます。

nicopinnicopin

|=演算子

演算子 |= は、C言語や他の多くのプログラミング言語において、ビット単位のOR代入演算子です。この演算子は、変数の値と特定のビットマスクをビット単位のOR操作で組み合わせ、その結果を元の変数に格納する際に使用されます。

ビット単位のOR操作とは

ビット単位のOR操作では、2つのビット列が比較され、どちらか一方または両方のビットが1であれば、結果の同じ位置のビットは1になります。具体的には、以下のように動作します:

0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1
|= 演算子の動作
|= 演算子を使用すると、左辺の変数の各ビットと右辺の各ビットをOR操作し、その結果を左辺の変数に再代入します。これは次の2つのステップを1つのステップに簡略化した形です:

byte = byte | mask;

この式を |= を使って書くと以下のようになります:

byte |= mask;
byte = 0b10101010; // byte変数を2進数で初期化
mask = 0b11000011; // マスク変数を2進数で初期化
byte |= mask;

この操作後の byte の値をビット単位で計算すると:
初期の byte: 10101010
mask: 11000011
byte |= mask の結果: 11101011
これは、byte の値に mask の1が設定されたビットが追加されたことを意味します。ビット位置でどちらかが1ならば結果も1になるためです。

この演算子は、特定のビットをセット(1にする)する場合に便利です。特にフラグ管理や状態管理、設定オプションの更新などでよく使用されます。

nicopinnicopin

ビットマスク

プログラミングにおける「マスク」(mask)は、特定のビットのみを選択的に操作するために用いるビットパターンです。ビットマスクは、データの一部分だけに影響を与えたいとき、または特定のビット情報のみを抽出したいときに使用されます。

ビットマスクの目的と使用例

特定のビットの操作:

ビットマスクを使用して、変数内の特定のビットだけを変更することができます。たとえば、あるビットだけを1に設定したり、0にクリアしたりすることが可能です。

ビットの抽出:

特定のビットを読み取るためにマスクを使用して、他のビットは無視できます。これにより、特定のビット位置の値を確認したり、その値に基づいて操作を行ったりすることができます。

ビットのテスト:

マスクを使用して特定のビットがセットされているかどうかをテストすることができます。これは、フラグや設定オプションを確認する際に有用です。
ビットマスクの例
以下に、ビットマスクを使用した具体的な例を示します。

ビットをセットする:

例えば、8ビット変数で第3ビット(0から数えて)を1にセットしたい場合は、ビットマスク 0b00000100(10進数で4)を使用してOR操作を行います。

byte |= 0b00000100;

ビットをクリアする:

同じ変数で第3ビットを0にクリアしたい場合は、マスク 0b11111011(マスクの該当ビットだけが0)を使用してAND操作を行います。

byte &= 0b11111011;

ビットをチェックする:

第3ビットがセットされているかどうかを確認するために、同じマスクを使用してAND操作を行い、結果が0かどうかをチェックします。

if (byte & 0b00000100) {
    // 第3ビットがセットされている
}

ビットマスクを使用することで、データの特定の部分に対して非常に精密な操作を行うことが可能になり、プログラムの効率と柔軟性が向上します。