Seaside Laboratory

Posts

memset はバイト単位で処理をする

memset は危険なヤツだった。例えば以下のような配列を初期化するコードを書いたとする。

#define SIZE 10

int nBuffer[SIZE];

// 配列を 0xff で初期化
memset( nBuffer, 0xff, sizeof( int ) * SIZE );

int は 4 バイトなので、

-0--1--2--3--4--5--6--7--8--9--A--B--C--D--E--F
ff 00 00 00 ff 00 00 00 ff 00 00 00 ff 00 00 00

このように 4 バイト単位 (リトルエンディアンなので反転) で初期化されると思っていた。

コードのイメージとしては、

for ( int i = 0; i < SIZE; i++ )
{
    nBuffer[i] = 0xff;
}

for 文と同等の処理を想定していたが実際は、

-0--1--2--3--4--5--6--7--8--9--A--B--C--D--E--F
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

こうなっていた。よくよく考えてみたら memset の引数リストには項目当たりのサイズ指定が無い…。配列を 0 で初期化するときは、

memset( nBuffer, 0, sizeof( int ) * SIZE );

こんな書き方をよく使っていたので「memset = 配列初期化」というイメージがこびりついていた。

設定値をバイト単位に展開したとき、0xff だと 0xffffffff になってしまうが、0x00 なら 0x00000000 になるので問題がなかったというオチ。

標準関数の名前には一定の規則性があるので、chr が含まれているときは「文字を扱う関数だな」となるが、mem の場合は…と考えると、

名前 意味
chr 文字
str 文字列
mem 文字列 (終端なし)

こんな命名規則になっていたりするのだろうか。