はかせのラボ

私の頭の中を書いていく雑記ブログです

C++ ビットフィールド ~ビット単位でメモリ管理を行う~

あいさつ

どうも、hakaseです。
最近は遊戯王マスターデュエルにお熱でずっとランクマにこもっています。
そのうちマスターデュエルの記事も上げだすかもしれません。
いつぞやのポケモンみたく、
またなんかゲームの記事上げてんなくらいに思って置いてください。

ただ今回はちゃんと技術記事です。
(技術系とそれ以外でブログ分けることも検討中・・
ただ管理がめんどいので結局やんない可能性高)

今回は表題にもある「ビットフィールド」という機能の紹介です。

ビットフィールド

端的に言うと構造体の各変数に割り当てるビット数を指定できる機能です。
細かい能書きの前にさっさとコードをば

// ビットフィールド無
struct Data
{
    unsigned int dataA;
    unsigned int dataB;
    unsigned int reserve;
}

// ビットフィールド有
struct Data2
{
    unsigned int dataA : 4;
    unsigned int dataB : 4;
    unsigned int reserve : 24; // 別に必須ではない
}

違いがわかりやすいように
ビットフィールド無(Data)/有(Data2)でそれぞれ書いてみました。

それぞれの違いは変数の後に
「コロン+数値」のよくわからんものがついてるかぐらいです。

ではここで唐突ですが問題です。
DataとData2のサイズはどれくらいでしょう?
ここでのサイズは素直にsizeofで得られる数値のことを指します。

コードに起こすとこんな感じのコードで得られる出力

auto size = sizeof(Data);
auto size2 = sizeof(Data2);
std::cout << size << "\n" << size2;

特にシンキングタイム用に結果を隠したり
長~い空白を置くこともなく結果です。
f:id:hakase0274:20220321004915p:plain

Data : 12byte
Data2 : 4byte
約3倍の差ですね。

Dataはunsigned int(以下uint)の変数を3つ持っています。
みなさんご存知uintは4byteの変数です。
それが3つあるので当然構造体のサイズは12byteになります。

Data2も持っている変数の型と数は同じです。
ただ各変数に割り当てるビット数を指定しています。
上から順に
4bit
4bit
24bit
以上の計32bit=4byteです。
そのため実際に割り当てられるサイズは4byteとなっているわけです。

ちなみにコメントで必須ではないと書いたreserveがなけりゃ
8bit=1byteになんじゃないのと思いませんか?
まぁそうなる環境もあると思いますが、
我々が良く使うvsのコンパイラは基本32bit単位で割り振るようなので
仮に8bitの構造体だろうが問答無用で32bit振られます。
コメントアウトするなりしてreserveを消して試せばその環境でどうなるかわかります。

なのであっても無くても変わりませんが、
「この分今余ってるから追加するならここから取ってってね!」
ぐらいの温度感でこの変数は置いてます。

割り振るビット数以上の値入れようとしたら?

さてビット数を指定できるということは
実質的に値制限をかけているようなものになります。
では気になるのはオーバーフローした際はどうなるのか?

さっきから出してる4bitでとれる値範囲は
0~15で16以上の値は入らないはずです。

ということで16を突っ込んでみましょう。

auto data2 = new Data2();
data2->dataA = 16;
std::cout << data2->dataA;
delete data2;

結果
(vs2019のデバッガでの表示)
f:id:hakase0274:20220321012733p:plain
ちゃんと0ですし、
次の変数にメモリがあふれているようなこともないです。
うっかりビット数以上の値を入れようとしても
大事故になったりはしなさそうですね。

実際使うん?

近年のマシンはみんなメモリが潤沢なので
こんなビット単位でメモリを管理する必要があるのかという
疑問が当然出てくると思います。

ぶっちゃけよくあるソフト開発とかであれば
無縁かなぁと思います。
PCやiOSAndroidとかでビット単位でメモリ切り詰めなきゃ
メモリ足りないなんて事態そう起こらないでしょうし、
もし起こってるんならそれは多分別のところで
なんかやばいことが起こってる可能性が高いです。

あとビット単位の管理になると
コンパイラとか環境の影響もモロに受けますし、
その影響で移植性も低くなります。

じゃあ必要な場面ないやんけと思うじゃないですか。
あるんですよ。必要な場面が。
ゲーム開発(コンシューマ機)っていうんですけど。

この分野はなぜかメモリがいくら増えても
メモリが足りないとかいうバグみたいな現象が常日頃起きるので
詰めれる場所は詰めておきたいんですよ。
そうたとえ1bitであっても。
1bitを8回詰めれば1byte空きますからね。

あとがき

今回はビットフィールドの紹介でした。
実は今回はあいさつでも書いた
マスターデュエルの記事書こうと思ってたんですが、
ビットフィールド紹介を実は書いてなかったという
衝撃の事実に気づいてしまい急遽こっちに舵を取った形です。

いやぁ・・
書いてたつもりだったんですがねぇ・・
まぁ気づいて書いたのだから結果オーライ。
記事書けてエライ。

それでは今回はこの辺でノシ

一応生きていますということと諸々の近況報告

あいさつ

お久しぶりです。hakaseです。
約一年ぶりの更新となってしまい申し訳ありませんorz

いつもみたいに忙しかったから~とか
書けない内容だったから~とか言うわけではなく
シンプルに休んでました。
(やってたことのうち書けるの何割あるのって言われたら大分無いんですが・・・)

ただ休んでる間に二転三転と業務内容が変わり
関わる技術内容もかなり変わりました。
あと一応少しですが趣味も増えてたりします。

なのでその辺の紹介を執筆リハビリがてら
今回の記事でできたらなーという感じです。
適当な暇つぶしにでもチラ見してもらえれば幸いです。

業務にかかる技術内容

今までゲーム業界に入るということを目的に
数学の基礎知識やら描画の基礎知識やら
所謂知っとけ系の技術をメインに触ってきました。
就職してからの1、2年目もその延長線上のことをやってました。

ただ実際にゲーム業界で働いてく中で自分のやりたいなぁって思うことが、
コンテンツそのものを作ることより
コンテンツ作りを楽にするってことに興味があるんだと気づいてきました。

なので職場の上司とかと話して、
現在はそういうサポート系の技術開発や研究を行っています。
イメージしやすいのはjenkinsとかを使ったCIとか、
効率化のためのWebアプリやツールあたりでしょうか。
多分それ系も遠くない未来やります。

前回までのそのそ勉強がてら書いてたxamlやらMVVMやらも
ちょろちょろ触るというか今割と業務で書いてます。

なのでプログラム言語的な変遷を書くと
今まではC++メインで時たまC#だったのが
C#xamlメインの時たまC++Python、その他WebAPIといった感じなので、
それに伴ってこのブログに登場する頻度もそんな感じになると思います。

当然業務で実際に何やったかを直接は書けないので
やった過程で見知ったことの共有や
内容を汎用化して書くといった感じになります。

趣味

過去記事に上がったようにポケモンを始め
デジタルゲームは相も変わらずやっています。

増えた趣味はデュエマとポケカです。
どっちも友達に誘われて始めてハマりました。
ぶっちゃけDCGがあるんだからそっちでいいやんと思ってたんですが、
実際に紙のTCGをやってみると紙そのものが持つ魅力というのは
確かにあると感じました。

電子書籍がある中紙の本が売れるのにも通じるものがあるかもしれませんね。
いつかこの辺のプレイ体験の差とかの考察とかも出来たら面白いかもしれません。

あと趣味と言えるかは不明ですが、
VTuberとかYoutuberとか所謂配信者を色々みるようになりました。
今まで動画を見ると言ったら「誰が」やっているかは割とどうでもよくて、
「何をしているか」という部分だけ見ていました。

ただ友達や会社の同期先輩とかから「○○の動画おもろいよ」とか
「○○のライブに当選したんだ」という話を聞くようになって
今まで大して興味を持つことがなかった
配信者そのものにも興味を持つようになってきました。

とりあえず履修しとけ枠でVTuberにじさんじとホロライブ、
YoutuberはHIKAKINやはじめしゃちょーあたりから
ちまちま見ています。
おすすめの配信者とかいたら教えてもらえるとうれしいです。

あとがき

約一年ほど寝かせてしまっていたこのブログですが、
またちまちまと書けるときに書いていこうかなと思っています。

とはいえ以前のように毎日投稿!とか少なくとも毎月投稿!
というようにある程度定期的にやろうとすると
書きたいこと・書けることがあるうちはいいんですが、
ないときに辛い気持ちになってしまうので
書きたいときに書くという不定期投稿にしていこうと思います。

また書く内容も以前みたいに
技術メイン!ゲームとかもちょろちょろ書くよ!って感じじゃなくて
書きたいときに書きたいものを書く!的な感じでやっていきます。
でも多分大体前までと書く内容そんな変わらんはずです。

まぁそんな感じで、
当ブログゆるっと再始動していきますので、
また改めてよろしくお願いします。

それでは今回はこの辺でノシ