C言語における演算子の解説

C言語で利用される様々な演算子について解説します。

算術演算子

基本的な算術演算を行います。

  • + (加算)
  • - (減算)
  • * (乗算)
  • / (除算)
  • % (剰余)

整数同士の除算では小数点以下は切り捨てられます。剰余演算子は、除算の余りを求めます。

#include <stdio.h>

int main() {
    int quotient = 9 / 2; // 結果は4 (整数除算)
    printf("Quotient: %d\n", quotient);

    float preciseQuotient = 9.0f / 2.0f; // 結果は4.5
    printf("Precise Quotient: %f\n", preciseQuotient);

    int remainder = 9 % 2; // 結果は1
    printf("Remainder: %d\n", remainder);

    return 0;
}

シフト演算子

ビット列を左右にシフトさせます。

  • << (左シフト)
  • >> (右シフト)

これらの演算子は、オペランドの2進数表現をビット単位で操作します。

#include <stdio.h>

int main() {
    int value = 2; // 2進数で 0010
    int shiftedValue = value << 1; // 1ビット左にシフト -> 0100 (10進数で4)
    printf("Shifted value: %d\n", shiftedValue); // 出力: 4

    return 0;
}

ビット演算子

ビット単位での論理演算を行います。

  • & (ビット単位AND)
  • | (ビット単位OR)
  • ^ (ビット単位XOR)

代入演算子

値の代入や、計算結果の代入を行います。

  • = (代入)
  • += (加算して代入)
  • -= (減算して代入)
  • *= (乗算して代入)
  • /= (除算して代入)
  • &= (ビット単位ANDして代入)
  • ^= (ビット単位XORして代入)
  • |= (ビット単位ORして代入)
  • >>= (右シフトして代入)
  • <<= (左シフトして代入)
#include <stdio.h>

int main() {
    int count = 5;
    count += 3; // count は 8 になる (count = count + 3 と同じ)
    printf("count after +=: %d\n", count);

    int data = 10;
    data %= 3; // data は 1 になる (data = data % 3 と同じ)
    printf("data after %%=: %d\n", data);

    return 0;
}

単項演算子

一つのオペランドに対して作用する演算子です。

  • ! (論理否定)
  • - (符号反転)
  • + (符号そのまま)
  • & (アドレス演算子)
  • sizeof (サイズ演算子)
  • ~ (ビット単位否定)
  • -- (デクリメント)
  • ++ (インクリメント)
  • * (間接参照演算子 / デリファレンス演算子)
  • (型) (キャスト演算子 / 型変換)

C言語では、0 は偽、非0 は真とみなされます。

1. 論理否定 (!)

オペランドの真偽を反転させます。

#include <stdio.h>

int main() {
    int flag = 0; // 偽
    int invertedFlag = !flag; // 真 (1) になる
    printf("Original flag: %d, Inverted flag: %d\n", flag, invertedFlag);

    return 0;
}

2. sizeof 演算子

オペランドのメモリ上のサイズをバイト単位で返します。

#include <stdio.h>

int main() {
    printf("Size of int: %zu bytes\n", sizeof(int));
    printf("Size of float: %zu bytes\n", sizeof(float));

    int numbers[5];
    printf("Size of array 'numbers': %zu bytes\n", sizeof(numbers));
    printf("Size of one element in 'numbers': %zu bytes\n", sizeof(numbers[0]));

    // 配列の要素数を計算
    size_t elementCount = sizeof(numbers) / sizeof(numbers[0]);
    printf("Number of elements in 'numbers': %zu\n", elementCount);

    return 0;
}

3. ビット単位否定 (~)

オペランドの各ビットを反転させます (0を1に、1を0に)。

整数は、符号ビットを含む3つの表現形式(原码、反码、補码)で扱われます。コンピュータは通常、補码で整数を格納します。

#include <stdio.h>

int main() {
    int val = 0; // 2進数で ...00000000
    // ~val は、すべてのビットが反転するので ...11111111 (補码表現で -1)
    printf("Bitwise NOT of 0: %d\n", ~val); // 出力: -1

    int num = 5; // 2進数で ...00000101
    // ~num は ...11111010 (補码表現で -6)
    printf("Bitwise NOT of 5: %d\n", ~num); // 出力: -6

    return 0;
}

4. インクリメント/デクリメント (++ / --)

オペランドの値を1増減させます。前置と後置で動作が異なります。

前置インクリメント (++variable)

先に値をインクリメントし、その後、インクリメントされた値を使用します。

#include <stdio.h>

int main() {
    int counter = 10;
    int result = ++counter; // counter が 11 になり、その値 (11) が result に代入される
    printf("Counter: %d, Result: %d\n", counter, result); // 出力: Counter: 11, Result: 11

    return 0;
}

後置インクリメント (variable++)

先に元の値を使用し、その後、値をインクリメントします。

#include <stdio.h>

int main() {
    int counter = 10;
    int result = counter++; // counter の元の値 (10) が result に代入され、その後 counter が 11 になる
    printf("Counter: %d, Result: %d\n", counter, result); // 出力: Counter: 11, Result: 10

    return 0;
}

5. キャスト演算子 ((型))

明示的にデータ型を変換します。

#include <stdio.h>

int main() {
    // 浮動小数点数を整数型に変換 (小数点以下は切り捨てられる)
    int intValue = (int)3.14159;
    printf("Casted int value: %d\n", intValue); // 出力: 3

    return 0;
}

関係演算子

二つのオペランドを比較し、真偽 (1または0) を返します。

  • > (より大きい)
  • >= (以上)
  • < (より小さい)
  • <= (以下)
  • != (等しくない)
  • == (等しい)

論理演算子

オペランドの真偽に基づいて、論理的なANDまたはOR演算を行います。

  • && (論理AND)
  • || (論理OR)
#include <stdio.h>

int main() {
    int conditionA = 5; // 真
    int conditionB = 0; // 偽

    int logicalAND = conditionA && conditionB; // 両方真ではないので偽 (0)
    printf("Logical AND: %d\n", logicalAND);

    int logicalOR = conditionA || conditionB; // Aが真なので真 (1)
    printf("Logical OR: %d\n", logicalOR);

    return 0;
}

条件演算子 (三項演算子)

3つのオペランドを取り、条件に基づいて値を返します。

条件式 ? 真の場合の値 : 偽の場合の値

#include <stdio.h>

int main() {
    int x = 10;
    int y = 20;
    int largerValue;

    // if-else 文での実装
    if (x > y) {
        largerValue = x;
    } else {
        largerValue = y;
    }
    printf("Larger value (if-else): %d\n", largerValue);

    // 三項演算子での実装
    largerValue = (x > y) ? x : y;
    printf("Larger value (ternary operator): %d\n", largerValue); // 出力: 20

    return 0;
}

カンマ演算子

複数の式を左から右へ順に評価し、最後の式の値を返します。

式1, 式2, 式3, ...

#include <stdio.h>

int main() {
    int a = 1;
    int b = 5;
    int c = 10;

    // (a = b + 2) -> a は 7 になる
    // (c = a - 4) -> c は 3 になる
    // (b = c + 2) -> b は 5 になる
    // カンマ式全体の結果は最後の式 (b = c + 2) の結果、つまり 5 になる
    int result = (a = b + 2, c = a - 4, b = c + 2);

    printf("a: %d, b: %d, c: %d, result: %d\n", a, b, c, result);
    // 出力: a: 7, b: 5, c: 3, result: 5

    return 0;
}

配列要素アクセス、関数呼び出し、構造体メンバーアクセス

  • [] (配列添字演算子)
  • () (関数呼び出し演算子)
  • . (構造体メンバーアクセス演算子)
  • -> (構造体ポインタメンバーアクセス演算子)

1. 配列添字演算子 ([])

配列の指定したインデックスの要素にアクセスします。

#include <stdio.h>

int main() {
    int dataArray[5] = {10, 20, 30, 40, 50};
    // dataArray[2] は 3 番目の要素 (値は 30) にアクセス
    printf("Element at index 2: %d\n", dataArray[2]); // 出力: 30

    return 0;
}

2. 関数呼び出し演算子 (())

関数を実行します。

#include <stdio.h>

// 簡単な関数定義
void greet() {
    printf("Hello from greet function!\n");
}

int add(int x, int y) {
    return x + y;
}

int main() {
    greet(); // greet 関数を呼び出す
    int sum = add(15, 25); // add 関数を呼び出し、結果を sum に代入
    printf("Sum of 15 and 25: %d\n", sum); // 出力: 40

    return 0;
}

タグ: C言語 演算子 算術演算子 シフト演算子 ビット演算子

9月28日 16:15 投稿