memset如何将整数数组初始化为-1?

hac*_*cks 61 c c++ arrays memset twos-complement

联机帮助页memset:

#include <string.h>
void *memset(void *s, int c, size_t n)
Run Code Online (Sandbox Code Playgroud)

memset()功能填充第一n 字节的存储器区域的指向s与恒定字节c.

很明显,memset不能用于初始化int数组,如下所示:

int a[10];
memset(a, 1, sizeof(a));  
Run Code Online (Sandbox Code Playgroud)

它是因为int由4个字节(比如说)表示,并且一个不能得到数组中整数的所需值a.
但我经常看到程序员 memset用来将int数组元素设置为0或者-1.

int a[10];
int b[10];
memset(a, 0, sizeof(a));  
memset(b, -1, sizeof(b));  
Run Code Online (Sandbox Code Playgroud)

根据我的理解,使用整数初始化0是可以的,因为0可以用1个字节表示(在这种情况下可能是我错了).但是,如何可以初始化b-1(一个4个字节的值)?

das*_*ght 69

奇怪的是,这个工作-1的原因与使用零的原因完全相同:在二进制补码二进制表示中,无论整数的大小如何,-11在其所有位中都有s,因此填充一个填充了字节的区域所有1s 在两个补码硬件上产生一个带-1符号ints,longs和shorts 的区域.

在与二进制补码不同的硬件上,结果会有所不同.的-1整数常数将被转换成一个unsigned char全部为,因为标准是特定的转换必须如何进行.但是,1根据平台的规则,将其所有位设置为的字节区域将被解释为整数值.例如,在符号和大小的硬件上,数组的所有元素都将包含相应类型的最小负值.

  • 不会使用`~0`实际上是相同的(更清楚)? (16认同)
  • @FiddlingBits是的,使用`~0`绝对可以避免混淆. (2认同)
  • @hackks 如果用全 1 位模式填充与某种整数类型(`int`、`long` 或 `short`)的 `sizeof` 相对应的内存区域,然后将该区域重新解释为相应的整数类型,您会在具有两个补码表示的计算机上看到“-1”。请注意,在极少数情况下,当您拥有符号大小硬件时,您会看到该硬件上可表示的最小负整数(我从未见过这样的硬件,甚至没有人提到见过这样的硬件,但我听说它确实存在) . (2认同)
  • @chux标准说,为了将负整数值转换为`unsigned`,编译器必须从2 ^ N中减去负值的大小,其中N是无符号整数类型中的位数.这里,N是8,因此结果是256-1 = 255,一个无符号值.这就是他们如何避免在不需要2s补码表示的情况下定义流程实现的方法.这就是为什么我的理解是`-1`将被转换为全1位模式,而不管在目标平台上表示否定的方式. (2认同)

Min*_*mal 5

当一个数的所有位都为 时0,其值也为0。但是,如果所有位1值是-1

如果我们写入int a[2],则会分配4x2字节的内存,其中包含随机/垃圾位-

00110000 00100101 11100011 11110010    11110101 10001001 00111000 00010001
Run Code Online (Sandbox Code Playgroud)

然后,我们写memset(a, 0, sizeof(a)). 现在,memset()逐字节工作,0 的一字节表示 ( unsigned char)是. 于是,就变成——00000000

00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000
Run Code Online (Sandbox Code Playgroud)

因此,a[0]a[1]都初始化为0


现在,让我们看看memset(a, -1, sizeof(a))-1 的一个字节是11111111. 而且,我们得到——

11111111 11111111 11111111 11111111    11111111 11111111 11111111 11111111
Run Code Online (Sandbox Code Playgroud)

在这里,a[0]a[1]都将具有值-1


但是,对于memset(a, 1, sizeof(a)):一个字节中的100000001-

00000001 00000001 00000001 00000001    00000001 00000001 00000001 00000001
Run Code Online (Sandbox Code Playgroud)

因此,该值将是- 16843009