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

C++で使えるGCCコンパイラの組み込み関数(__builtin)の使い方まとめ

GCCコンパイラには、標準ライブラリとは別に便利な組み込み関数(ビルトイン関数)が多数用意されています。これらはコンパイラレベルで最適化されるため、非常に高速に動作し、特に競技プログラミングやビット演算処理で重宝します。

本記事では、代表的な組み込み関数である __builtin_popcount()__builtin_parity()__builtin_clz()__builtin_ctz() の使い方をサンプルコード付きで解説します。

__builtin_popcount(x):1のビット数を数える

__builtin_popcount(x) は、整数型データの2進表現において、1になっているビットの個数を返す関数です。「母集団カウント(popcount)」とも呼ばれます。

サンプルコード

#include<iostream>
using namespace std;
int main() {
    int n = 13; // 2進数では 1101
    cout << n << " の2進表現に含まれる1の個数は " << __builtin_popcount(n);
    return 0;
}

実行結果

13 の2進表現に含まれる1の個数は 3

13 は2進数で 1101 となり、1が3つ含まれているため「3」が出力されます。

__builtin_parity(x):パリティ(偶奇性)を判定する

__builtin_parity(x) は、整数のパリティを判定する関数です。1のビット数が奇数であれば true(1) を、偶数であれば false(0) を返します。

サンプルコード

#include<iostream>
using namespace std;
int main() {
    int n = 13; // 2進数では 1101
    cout << n << " のパリティは " << __builtin_parity(n);
    return 0;
}

実行結果

13 のパリティは 1

13(1101)は1のビットが3つと奇数個あるため、結果は「1」となります。

__builtin_clz(x):先頭の連続する0を数える

__builtin_clz(x) は、整数の2進表現における先頭側(最上位ビット側)の連続した0の個数を返します。「clz」は Count Leading Zeros(先頭のゼロを数える)の略です。

サンプルコード

#include<iostream>
using namespace std;
int main() {
    int n = 13; // 2進数では 1101
    // 0000 0000 0000 0000 0000 0000 0000 1101(32ビット整数)
    cout << n << " の先頭にある0の個数は " << __builtin_clz(n);
    return 0;
}

実行結果

13 の先頭にある0の個数は 28

32ビット整数の場合、全体は32桁なので、有効なビット4桁(1101)を除いた 32 − 4 = 28 個の先頭ゼロがカウントされます。

注意: 引数に 0 を渡した場合の動作は未定義です。実行前に必ず値が0でないことを確認してください。

__builtin_ctz(x):末尾の連続する0を数える

__builtin_ctz(x) は、整数の2進表現における末尾側(最下位ビット側)の連続した0の個数を返します。「ctz」は Count Trailing Zeros(末尾のゼロを数える)の略です。

サンプルコード

#include<iostream>
using namespace std;
int main() {
    int n = 12; // 2進数では 1100
    // 0000 0000 0000 0000 0000 0000 0000 1100(32ビット整数)
    cout << n << " の末尾にある0の個数は " << __builtin_ctz(n);
    return 0;
}

実行結果

12 の末尾にある0の個数は 2

12(1100)は末尾に0が2つ続くため、結果は「2」となります。この値は「nを割り切れる2の最大乗」に相当するため、2の累乗計算にも応用できます。

補足:64ビット整数や他コンパイラへの対応

  • long 型や long long 型に対しては、それぞれ __builtin_popcountl() / __builtin_popcountll() のように末尾に lll を付けたバージョンを使用します。
  • これらの関数はGCC固有の拡張機能であり、C++の標準規格には含まれていません。MSVCなど別のコンパイラでは使えない場合があるため、移植性が必要なコードでは注意してください。
  • C++20以降では、標準ライブラリの <bit> ヘッダにある std::popcount()std::countl_zero()std::countr_zero() などを使うことで、同様の処理を移植性高く記述できます。

  1. C++のswap()関数とは?2つの変数の値を入れ替える方法をサンプルコード付きで解説

    swap()関数とは C++のswap()関数は、2つの値を入れ替える(交換する)ための関数です。この関数を利用すれば、一時的な第三の変数を自分で用意することなく、2つの変数の値を簡単に入れ替えることができます。 swap()関数の構文 void swap(int variable_name1, int variable_name2); 変数に値を代入してswap()関数に渡した場合、関数内では値の入れ替えが行われますが、呼び出し元の実際の変数の値は変わりません。これは、引数が「値渡し」で渡されるためです。実際の変数の値を入れ替えたい場合は、後述する「参照渡し」を使用します。 例1:s

  2. LinuxにC++コンパイラをインストールする方法(GCC・Clangの手順を解説)

    Linux上でC++プログラムをコンパイルするには、いくつかの選択肢があります。本記事では、代表的な2つのコンパイラ「GCC」と「Clang」の確認方法およびインストール手順について解説します。 GCCの確認とインストール ほとんどのLinuxディストリビューションには、標準でGCC(GNU Compiler Collection)がインストールされています。まずは、お使いのシステムにGCCが導入されているかどうかを確認しましょう。ターミナル(コマンドライン)から以下のコマンドを実行してください。 $ g++ -v GCCがすでにインストールされている場合は、次のようなバージョン情報が表示され