13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C++Advent Calendar 2023

Day 14

C++23便利機能の紹介:byteswap関数

Last updated at Posted at 2023-12-13

C++23標準ライブラリでは「バイト単位での順序入れ替え」を行う関数テンプレート std::byteswap が追加されました。

C++20機能を利用したエンディアン判定(std::endian)と組み合わせて、整数型のネットワークバイトオーダー ⇔ ホストバイトオーダー変換を汎用的に記述できます。

POSIX.1-2001
// <arpa/inet.h>ヘッダ
uint32_t htonl(uint32_t);
uint16_t htons(uint16_t);
uint32_t ntohl(uint32_t);
uint16_t ntohs(uint16_t);
// WindowsOSは<winsock.h>ヘッダで同等関数を宣言
C++23
#include <bit>
#include <concepts>

template <std::integral T>
constexpr inline T hton(T value) noexcept
{
  if constexpr (std::endian::native == std::endian::little) {
    return std::byteswap(value);
  } else {
    return value;
  }
}

template <std::integral T>
constexpr inline T ntoh(T value) noexcept
{
  if constexpr (std::endian::native == std::endian::little) {
    return std::byteswap(value);
  } else {
    return value;
  }
}

これでもう64ビット幅整数のバイトスワップ関数1を探す必要もなくなり、将来に備えて128ビット幅整数(要る?)のバイトスワップ処理だって簡単に書けちゃいます!

EXTRA STAGE

以降は onihusube🍄さん からの鋭い指摘 追加ネタご提供をもとに追記した内容です。寂しかった記事を増強させるきっかけを頂いたことに感謝。

この世の中にはリトルエンディアン/ビッグエンディアンどちらでも無い、独自の エンディアン をもつアーキテクチャが存在するそうです。例えば往年の PDP-11 とか。

C++標準ライブラリはこの点を考慮した仕様となっており、std::endian::nativestd::endian::little, std::endian::bigいずれでもない処理系定義の値をとる可能性があります。さすが俺たち/私たちのC++!!

C++23
#include <bit>
#include <concepts>

template <std::integral T>
constexpr inline T hton(T value) noexcept
{
  if constexpr (std::endian::native == std::endian::little) {
    return std::byteswap(value);
  } else if constexpr (std::endian::native == std::endian::big) {
    return value;
  } else {
    static_assert(false, "Unknown endianness");
  }
}

template <std::integral T>
constexpr inline T ntoh(T value) noexcept
{
  if constexpr (std::endian::native == std::endian::little) {
    return std::byteswap(value);
  } else if constexpr (std::endian::native == std::endian::big) {
    return value;
  } else {
    static_assert(false, "Unknown endianness");
  }
}

else節の static_assert(false, "..."); が気になったあなた。かなりC++にお詳しいですね?確かに以前のC++仕様ではこの書き方だとconstexpr if文の分岐状況によらずコンパイルエラーを引き起こしていました。2023年12年現在では プログラマの意図通りに振る舞うよう修正 されています。ちゃんとユーザフレンドリに進化してるんですね〜

関連情報

  1. htonll/ntohll, bswap_64, _byteswap_uint64, etc...

13
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?