C言語、C++、Rustで関数を使ってビット操作をする
はじめに
C23以降のC言語、C++20以降のC++、Rustは関数(メソッド)を使ってビット操作をすることができます。
これらの関数はC言語では<stdbit.h>、C++では<bit>、Rustではプリミティブ整数型のメソッドとして定義されています。
この記事では、これらの関数を操作ごとに紹介します。
整数値が2の累乗かを判定する
C言語ではstdc_has_single_bit関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_has_single_bit(0b10000u));
C++ではstd::has_single_bit関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::has_single_bit(0b10000u));
Rustではis_power_of_twoメソッドを使って求めることができます。
assert!(0b10000_u32.is_power_of_two());
整数値を2の累乗値に切り上げる
C言語ではstdc_bit_ceil関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_bit_ceil(3u) == 4);
C++ではstd::bit_ceil関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::bit_ceil(3u) == 4);
Rustではnext_power_of_twoメソッドを使って求めることができます。
assert_eq!(3_u32.next_power_of_two(), 4);
整数値を2の累乗値に切り下げる
C言語ではstdc_bit_floor関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_bit_floor(0b0110'0100u) == 0b0100'0000);
C++ではstd::bit_floor関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::bit_floor(0b0110'0100u) == 0b0100'0000);
Rustではisolate_most_significant_oneメソッドを使って求めることができます。
現時点ではこのメソッドはnightlyチャンネルでのみ利用できます。
#![feature(isolate_most_least_significant_one)]
assert_eq!(0b0110_0100_u32.isolate_most_significant_one(), 0b0100_0000);
整数値を表現するのに必要な最小ビット数を求める
C言語ではstdc_bit_width関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_bit_width(0b1110u) == 4);
C++ではstd::bit_width関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::bit_width(0b1110u) == 4);
Rustではbit_widthメソッドを使って求めることができます。
現時点ではこのメソッドはnightlyチャンネルでのみ利用できます。
#![feature(uint_bit_width)]
assert_eq!(0b1110_u32.bit_width(), 4);
最上位ビットから連続する0のビットを数える
C言語ではstdc_leading_zeros関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
#include <stdint.h>
assert(stdc_leading_zeros(UINT32_MAX >> 2) == 2);
C++ではstd::countl_zero関数を使って求めることができます。
#include <bit>
#include <cassert>
#include <cstdint>
assert(std::countl_zero(UINT32_MAX >> 2) == 2);
Rustではleading_zerosメソッドを使って求めることができます。
assert_eq!((u32::MAX >> 2).leading_zeros(), 2);
最下位ビットから連続する0のビットを数える
C言語ではstdc_trailing_zeros関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_trailing_zeros(0b010'1000u) == 3);
C++ではstd::countr_zero関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::countr_zero(0b010'1000u) == 3);
Rustではtrailing_zerosメソッドを使って求めることができます。
assert_eq!(0b010_1000_u32.trailing_zeros(), 3);
最上位ビットから連続する1のビットを数える
C言語ではstdc_leading_ones関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
#include <stdint.h>
assert(stdc_leading_ones(~(UINT32_MAX>>2)) == 2);
C++ではstd::countl_one関数を使って求めることができます。
#include <bit>
#include <cassert>
#include <cstdint>
assert(std::countl_one(~(UINT32_MAX >> 2)) == 2);
Rustではleading_onesメソッドを使って求めることができます。
assert_eq!((!(u32::MAX >> 2)).leading_ones(), 2);
最下位ビットから連続する1のビットを数える
C言語ではstdc_trailing_ones関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_trailing_ones(0b101'0111u) == 3);
C++ではstd::countr_one関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::countr_one(0b101'0111u) == 3);
Rustではtrailing_onesメソッドを使って求めることができます。
assert_eq!(0b101_0111_u32.trailing_ones(), 3);
1に設定されたビットを数える
C言語ではstdc_count_ones関数を使って求めることができます。
#include <assert.h>
#include <stdbit.h>
assert(stdc_count_ones(0b0100'1100u) == 3);
C++ではstd::popcount関数を使って求めることができます。
#include <bit>
#include <cassert>
assert(std::popcount(0b0100'1100u) == 3);
Rustではcount_onesメソッドを使って求めることができます。
assert_eq!(0b0100_1100_u32.count_ones(), 3);
まとめ
| C言語 | C++ | Rust | |
|---|---|---|---|
| 整数値が2の累乗かを判定する | stdc_has_single_bit |
std::has_single_bit |
is_power_of_two |
| 整数値を2の累乗値に切り上げる | stdc_bit_ceil |
std::bit_ceil |
next_power_of_two |
| 整数値を2の累乗値に切り下げる | stdc_bit_floor |
std::bit_floor |
isolate_most_significant_one |
| 整数値を表現するのに必要な最小ビット数を求める | stdc_bit_width |
std::bit_width |
bit_width |
| 最上位ビットから連続する0のビットを数える | stdc_leading_zeros |
std::countl_zero |
leading_zeros |
| 最下位ビットから連続する0のビットを数える | stdc_trailing_zeros |
std::countr_zero |
trailing_zeros |
| 最上位ビットから連続する1のビットを数える | stdc_leading_ones |
std::countl_one |
leading_ones |
| 最下位ビットから連続する1のビットを数える | stdc_trailing_ones |
std::countr_one |
trailing_ones |
| 1に設定されたビットを数える | stdc_count_ones |
std::popcount |
count_ones |
Discussion