Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C/C++で算術演算子を使わずに2つの整数を加算する方法を解説

このチュートリアルでは、C/C++において算術演算子(+、-など)を使わずに2つの整数を加算する方法について詳しく解説します。

算術演算子を使用せずに加算を実現するには、主に以下の2つのアプローチがあります。

  • ポインタを利用する方法
  • ビット演算子を利用する方法

それぞれの仕組みと実装例を見ていきましょう。

方法1:ポインタを使った加算

C言語では、配列の添字アクセス p[b] は内部的に *(p + b) として解釈されます。つまり、ポインタに対する添字操作には暗黙的にアドレスの加算が含まれています。この性質を利用すると、明示的に + 演算子を書かなくても加算を実現できます。

サンプルコード

#include <iostream>
using namespace std;

int sum(int a, int b) {
    int *p = &a;
    // p[b] は *(p + b) と等価なため、&p[b] は a のアドレスに b を加えた位置を指す
    return (int)&p[b];
}

int main() {
    int add = sum(2, 3);
    cout << add << endl;
    return 0;
}

出力結果

5

方法2:ビット演算子を使った加算

より移植性が高く推奨されるのが、ビット演算を用いる方法です。デジタル回路における加算器の動作と同じ原理に基づいています。

  • XOR(^):桁上がりを考慮しない部分和を求める
  • AND(&):桁上がり(キャリー)が発生する位置を検出する
  • 左シフト(<< 1):キャリーを1桁上に移動させる

キャリーが0になるまで、これらの処理を再帰的に繰り返すことで最終的な合計値が得られます。

サンプルコード

#include <iostream>
using namespace std;

int sum(int a, int b) {
    // XORで桁上がりなしの和を計算
    int s = a ^ b;
    // ANDでキャリーの発生位置を取得
    int carry = a & b;
    
    if (carry == 0)
        return s;   // キャリーがなければ完了
    else
        return sum(s, carry << 1);  // キャリーを左シフトして再帰処理
}

int main() {
    int add = sum(2, 3);
    cout << add << endl;
    return 0;
}

出力結果

5

まとめ

手法メリットデメリット
ポインタ方式コードが短い未定義動作の可能性があり、環境依存
ビット演算方式論理的に正しく、移植性が高い負数の扱いや再帰の深さに注意が必要

実務や学習の観点では、ビット演算による方法が安全かつ理論的にも美しいため推奨されます。ポインタ方式はC言語のメモリモデルへの理解を深める良い題材ですが、実際のコードでは未定義動作を引き起こす可能性があるため注意してください。

  1. C言語のポインタを使って2つの行列を乗算する方法をわかりやすく解説

    ポインタ(pointer)とは、別の変数のメモリアドレスを格納するための変数です。C言語ではポインタを使うことでメモリを直接操作でき、効率的で高速なプログラムを作成できます。 ポインタの特徴 メモリ空間を節約できる。 メモリ上の位置へ直接アクセスするため、実行速度が速い。 メモリの動的な割り当てと解放が可能になり、メモリを効率的に利用できる。 リンクリストや木構造などのデータ構造と組み合わせて使用される。 ポインタの宣言・初期化・アクセス まず、次のような通常の変数宣言を考えてみましょう。 int qty = 179; この変数はメモリ上では、「qty」という名前、値「179」、そして固有

  2. マージソートを使って配列の転倒数(反転数)を数えるC/C++プログラム

    転倒数(Inversion Count)とは?与えられた配列をソートする際に発生する反転(転倒)の回数を「転倒数(Inversion Count)」と呼びます。転倒数を求める問題は古典的なアルゴリズム問題の一つで、マージソート(Merge Sort)のアルゴリズムを応用することで効率的に解くことができます。この問題では、各要素について「自分より左側にあり、かつ自分より大きな値を持つ要素」の数をすべて数え上げ、その合計を出力します。この処理は、マージソートのマージ(merge)関数の中で実装されます。理解を深めるために、マージ処理で扱う2つの部分配列を例に考えてみましょう。配列の転倒数の定義配列