- cpp20[meta cpp]
C++20では、符号付き整数型のビット表現を「2の補数 (Two's Complement)」に規定する。
これによって、2の補数を前提としたビット演算ができるようになる。また、2の補数には値-0を表すビット値が存在しないため、「ビット値が異なる値0と値-0を等値であるとする」ということが起こらなくなる (1の補数や絶対値表現には-0を表すビット値がある)。これにより、符号付き整数型に対するハッシュ値が一意に定まり、strong ordering (強順序、全順序) の要件を満たすようになる (-0 < 0が成り立たなかったが、-0がなくなった)。
値-0は、0を意味する。
符号付き整数型に対する右シフトは「符号拡張 (sign extension)」を行い、符号ビットが右に伝播する。
ただし、符号付き整数型のオーバーフロー時の動作は、これまでと変わらず未定義動作である。std::numeric_limits<符号付き整数型>::is_moduloはデフォルトでfalseのままとなる。
#include <cassert>
#include <cstdint>
int main()
{
// 符号反転したビット値
{
std::int8_t x = 11;
assert(x == 0b0000'1011);
std::int8_t y = -x;
assert(y == (~x + 1)); // 負数は、ビット反転して+1した値
assert(y == static_cast<std::int8_t>(0b1111'0101));
}
// 0と-0は同じビット値
{
std::int8_t x = 0;
std::int8_t y = -0;
assert(x == static_cast<std::int8_t>(0b0000'0000));
assert(y == static_cast<std::int8_t>(0b0000'0000));
}
// 右シフト時の符号拡張
{
std::int8_t x = -124;
assert(x == static_cast<std::int8_t>(0b1000'0100));
x >>= 2;
assert(x == static_cast<std::int8_t>(0b1110'0001));
}
}- std::int8_t[link /reference/cstdint/int8_t.md]
#include <type_traits>
#include <cstdint>
int main()
{
static_assert(std::has_unique_object_representations<char>::value);
static_assert(std::has_unique_object_representations<short>::value);
static_assert(std::has_unique_object_representations<int>::value);
static_assert(std::has_unique_object_representations<long>::value);
static_assert(std::has_unique_object_representations<long long>::value);
static_assert(std::has_unique_object_representations<std::int8_t>::value);
static_assert(std::has_unique_object_representations<std::int16_t>::value);
static_assert(std::has_unique_object_representations<std::int32_t>::value);
static_assert(std::has_unique_object_representations<std::int64_t>::value);
}- std::has_unique_object_representations[link /reference/type_traits/has_unique_object_representations.md]
- std::int8_t[link /reference/cstdint/int8_t.md]
- std::int16_t[link /reference/cstdint/int16_t.md]
- std::int32_t[link /reference/cstdint/int32_t.md]
- std::int64_t[link /reference/cstdint/int64_t.md]
#include <type_traits>
#include <compare>
int main()
{
int a = 1;
int b = 2;
// 符号付き整数型はstrong orderingをもつ
auto r = a <=> b;
static_assert(std::is_same_v<decltype(r), std::strong_ordering>);
}- std::strong_ordering[link /reference/compare/strong_ordering.md.nolink]
Visual Studio、GCC、Clangといった主要な処理系が、2の補数以外をサポートしていなかった。
C11規格は、2の補数のほかに、1の補数表現 (Ones' complement) と符号ビット付き絶対値表現 (Signed magnitude) を許可しているが、C++では本文書の概要にも記載したように、ハッシュ値の一意性と全順序をサポートするため、2の補数に規定する。