manpage はmemset
について述べています:
_#include <string.h> void *memset(void *s, int c, size_t n)
_
memset()
関数は、n
が指すメモリ領域の最初のs
bytesを埋めます。定数バイトc
を使用します。
以下に示すように、memset
を使用してint
配列を初期化できないことは明らかです。
_int a[10];
memset(a, 1, sizeof(a));
_
これは、int
が4バイト(たとえば)で表され、配列a
の整数に必要な値を取得できないためです。
しかし、プログラマはmemset
を使用してint
配列要素を_0
_または_-1
_に設定することがよくあります。
_int a[10];
int b[10];
memset(a, 0, sizeof(a));
memset(b, -1, sizeof(b));
_
私の理解では、整数_0
_で初期化することは問題ありません。なぜなら_0
_は1バイトで表現できるからです(このコンテキストでは間違っているかもしれません)。しかし、b
を_-1
_(4バイトの値)で初期化する方法はありますか?
奇妙なことに、これが-1
で動作する理由は、これがゼロで動作する理由とまったく同じです。in 2の補数バイナリ表現 、-1
は1
sすべてのビットは、整数のサイズに関係なく、すべての1
sで埋められたバイトで領域を埋めると、-1
符号付きint
s、long
sの領域が生成されます。 、および2の補数のハードウェア上のshort
s。
2の補数とは異なるハードウェアでは、結果は異なります。 -1
整数定数は、すべてが1のunsigned char
に変換されます。これは、標準が変換の実行方法に固有であるためです。ただし、すべてのビットが1
に設定されているバイトの領域は、プラットフォームの規則に従って整数値として解釈されます。たとえば、符号と大きさのハードウェアでは、配列のすべての要素に、対応する型の最小の負の値が含まれます。
0
_の場合、その値もです。ただし、すべてのビットが_1
_の場合、値は-1です。
_int a[2]
_を書き込むと、 4x2 バイトのメモリが割り当てられます。
_00110000 00100101 11100011 11110010 11110101 10001001 00111000 00010001
_
次に、memset(a, 0, sizeof(a))
と記述します。現在、memset()
はint
とchar
を区別しません。 バイト単位で動作します。 の1バイト表現は_00000000
_です。それで、
_00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
_
したがって、_a[0]
_と_a[1]
_は両方ともで初期化されます。
今、memset(a, -1, sizeof(a))
を見てみましょう:-1の1バイトは_11111111
_です。そして、私たちは-
_11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
_
ここでは、_a[0]
_と_a[1]
_の両方の値は-1になります。
ただし、memset(a, 1, sizeof(a))
の場合:1バイトの1は_00000001
_-
_00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001
_
したがって、値は-16843009になります。