【C++】memset的陷阱

以前用过 memset,以为唯一的坑就是最后一个参数,没想到还有坑。

从下面的代码说起。

1
2
3
4
5
6
7
8
9
10
int road[10001];
int main()
{
while (cin >> L >> M)
{
//我们希望把 road 前 L 个元素设置为 1
memset(road, 1, sizeof(int) * L);
//....
}
}

然而这个代码运行是不成功的,因为 memset(road, 1, sizeof(int) * L); 并不会把 road 数组变成 1。我在查看时发现所有的元素都变成了 16843009

这他娘的就很见鬼了,我一开始还以为是系统的 bug 后来查了一下资料才发现是我对 memset 理解的错误。

1
memset(数组名, 值, sizeof(数组名));

因为memset是按字节赋值,对每个字节赋值同样的值,这样int四个字节会附相同的值(这也是它为什么是在 cstring 里的原因)。而0二进制代码全为0,不容易错。

那么赋值为 1 时呢?你看啊,一个 int 四个四节,每个字节变成 1,那就是:

00000001 00000001 00000001 00000001

转换成10进制也就是16843009。

以后用 memset 的时候就要注意了,一般拿它来置零就行了,要想赋值为别的值,就用 algorithm 里的 fill吧。

1
void fill (ForwardIterator first, ForwardIterator last, const T& val);

当然这个会稍微慢一点。

以后用 memset 需要注意了:

  1. 如果是针对 char 这样的单字节数组,哪么先设置什么就设置什么
  2. 如果是 int,那只有 0 和 -1 是有效的