memset 中的内存布局

Memory layout in memset

我有这个 "buggy" 代码:

int arr[15];
memset(arr, 1, sizeof(arr));

memset 将每个字节设置为 1,但由于 int 通常是 4 个字节,因此它不会给出所需的输出。我知道数组中的每个 int 都会初始化为 0x01010101 = 16843009。由于我对十六进制值和内存布局的理解很弱(非常),有人可以解释为什么它被初始化为那个十六进制值吗?如果我用 4 代替 1 会怎样?

如果我相信手册页

The memset() function writes len bytes of value c (converted to an unsigned char) to the string b.

在您的情况下,它将 0x00000001(作为 int)转换为 0x01(作为 unsigned char),然后用该值填充内存的每个字节。你可以把其中的4个放在一个int中,也就是说,每个int都会变成0x01010101。

如果你有4个,它会被转换成unsigned char 0x04,每个int会被0x04040404填充。

你觉得这有意义吗?

memset所做的是

Converts the value ch to unsigned char and copies it into each of the first count characters of the object pointed to by dest.

因此,首先将您的值(1) 转换为unsigned char,它占用1 个字节,因此将是0b00000001。然后 memset 将用这些值填充整个数组的内存。由于 int 在您的计算机上占用 4 个字节,因此数组中每个 int int 的值将是 00000001000000010000000100000001,即 16843009。如果您放置另一个值而不是 1,数组的内存将被该值填充。

请注意,memset 将其第二个参数转换为一个 unsigned char,即一个字节。一个字节是八位,您将每个字节设置为值 1。所以我们得到

0b00000001 00000001 00000001 00000001

或十六进制,

0x01010101

或十进制数16843009。为什么这个值?因为

0b00000001000000010000000100000001 = 1*2^0 + 1*2^8 + 1*2^16 + 1*2^24
                                   = 1 + 256 + 65536 + 16777216
                                   = 16843009

每组四个二进制数字对应一个十六进制数字。由于 0b0000 = 0x00b0001 = 0x1,您的最终值为 0x01010101。使用 memset(arr, 4, sizeof(arr)); 你会得到 0x04040404 而使用 12 你会得到 0x0c0c0c0c.