TheUnknownThing的技术分享站

Stay Hungry, Stay Foolish

我以后再也不用memset了……

默认分类 0 评 99 阅读

0. 前言

问题来源于大一下学期的第一次机考……这是一道分块的题目,程序里我有这样子的一个操作:

memset(mul_tag, 1, sizeof(mul_tag));

不出意外,程序WA了。我debug了太久太久,这行看起来根本没有问题啊?但事实上把这行改了就能对!Why???我们从 memset 函数原型来看,就能发现这个问题。

1. memset 函数简介

memset 函数的原型如下:

void *memset(void *s, int c, size_t n);
  • s: 指向要填充的内存块的指针。
  • c: 要设置的值。注意: c 虽然是 int 类型,但 memset 实际上是将 c 转换为 unsigned char 后进行填充。
  • n: 要填充的字节数。

memset 的作用是将 s 指向的内存块的前 n 个字节设置为 c 指定的值。

2. 陷阱

memset 是按字节进行填充的。当 a 是一个 int 数组(假设 int 占用 4 个字节)时,memset(a, 1, sizeof(a)) 会将每个 int 元素的每个字节都设置为 1。 这会导致每个 int 元素的值变成 0x01010101,即十进制的 16843009,而不是我们期望的 1

3. 例外

memset(a, 1, sizeof(a)) 大部分情况下是很危险的。但是,有几个例外情况它能够正常工作:

  • char 数组: 如果 achar 数组,memset(a, 1, sizeof(a)) 是正确的,因为 char 类型只占用一个字节。
  • 初始化为 0: memset(a, 0, sizeof(a)) 可以安全地用于任何类型的数组,用于将整个数组初始化为 0。(也就是我们平时所做的!这也是为什么我会认为memset(a, 1, sizeof(a))没问题!)
  • 初始化为 -1 (int类型): memset(a, -1, sizeof(a)) 对于int数组是安全的, 可以得到-1的结果.

4. 你应该用std::fill

std::fill 示例(C++):

#include <algorithm>
#include <array>

std::array<int, 10> a;  // 或者 int a[10];
std::fill(a.begin(), a.end(), 1); // 或者 std::fill(a, a + 10, 1);
快来做第一个评论的人吧~

:D 获取中...