16

使用空终止字符对整个字符数组进行 m​​emset 的正确和最安全的方法是什么?我可以列出一些用法:

...
char* buffer = new char [ARRAY_LENGTH];

//Option 1:             memset( buffer, '\0', sizeof(buffer) );
//Option 2 before edit: memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );
//Option 2 after edit:  memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );
//Option 3:             memset( buffer, '\0', ARRAY_LENGTH );
...
  • 这些中的任何一个是否比其他(S)具有显着优势?
  • 使用 1、2 或 3 时我会遇到哪些问题?
  • 处理此请求的最佳方式是什么?
4

8 回答 8

23

选项一和二是错误的。第一个使用指针的大小而不是数组的大小,因此它可能不会写入整个数组。第二个使用sizeof(char*)而不是sizeof(char)所以它会写到数组的末尾。选项3没问题。你也可以用这个

memset( buffer, '\0', sizeof(char)*ARRAY_LENGTH );

sizeof(char)保证为1。

于 2012-10-17T13:47:50.197 回答
13

惯用的方法是对数组进行值初始化:

char* buffer = new char [ARRAY_LENGTH]();

选项 1仅将第一个sizeof(char*)字节设置为 0,或者如果ARRAY_LENGTH < sizeof(char*). 这是由于使用指针的大小而不是类型的大小。

选项 2遇到未定义的行为,因为您尝试设置的字节数超过 ARRAY_LENGTH 字节。 sizeof(char*)几乎可以肯定大于 1。

由于这是 C++(newC 中没有),我建议您使用 astd::string代替。

对于 C(假设malloc不是new[]),您可以使用

memset( buffer, 0, ARRAY_LENGTH );
于 2012-10-17T13:44:38.207 回答
6

由于问题不断变化,我定义:

1:memset( buffer, '\0', sizeof(buffer) );

2a:memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );

2b:memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );

3:memset( buffer, '\0', ARRAY_LENGTH );

如果问题仅仅是“调用的正确方法是什么memset”而不是“将该数组归零的最佳方法是什么”,那么 2b 或 3 都是正确的。1 和 2a 是错误的。

您可以在 2b 与 3 上进行风格大战:是否包含sizeof(char)- 有些人将其省略,因为它是多余的(我通常这样做),其他人将其放入以创建一种与相同代码设置的一致性的数组int。也就是说,即使他们知道大小为 1,他们总是将大小乘以多个元素。一个可能的结论是,对指向的数组进行 m​​emset 的“最安全”方法buffer是:

std::memset(buffer, 0, sizeof(*buffer) * ARRAY_LENGTH);

如果缓冲区的类型发生变化,此代码仍然正确,当然前提是它继续具有ARRAY_LENGTH任何类型的元素,并且所有位为零仍然是正确的初始值。

“C++ is not C”程序员钟爱的另一个选择是:

/* never mind how buffer is allocated */
std::fill(buffer, buffer + ARRAY_LENGTH, 0);

如果您关心,您可以自行检查您的编译器是否将其优化为与优化对std::memset.

char *buffer = new char [ARRAY_LENGTH]();在实践中很漂亮但在 C++ 中几乎没用,因为你几乎从来没有new首先分配数组。

std::string buffer(ARRAY_LENGTH, 0);介绍了一种管理缓冲区的特定方式,这可能是也可能不是您想要的,但通常是。在char buffer[ARRAY_LENGTH] = {0};某些情况下有很多话要说。

于 2012-10-17T14:01:12.560 回答
4
  • 这些中的任何一个是否比其他(S)具有显着优势?
  • 使用 1、2 或 3 时我会遇到哪些问题?

第一个是错误的,因为sizeof(buffer) == sizeof(char*).

2号和3号都可以。

  • 处理此请求的最佳方式是什么?

为什么不只是:

buffer[0] = '\0';

如果这是一个char数组,为什么还要打扰其余的字符呢?将第一个字节设置为零,您""buffer.

当然,如果您真的坚持将所有内容buffer归零,请使用答案std::fill- 这是正确的方法。我的意思是std::fill(buffer, buffer + ARRAY_LENGTH, 0);

于 2012-10-17T14:09:42.903 回答
2

如果您绝对必须在 C++ 中使用原始数组(这是一个非常不好的主意),请这样做:

char* buffer = new char [ARRAY_LENGTH]();

因为 C++memset通常是无能者的最后避难所,尽管我在过去几个月中了解到,为了获得可接受的性能,使用当前的工具,当一个人实现自己的字符串类时,有必要降低到那个水平。

代替这些看起来可能需要的原始数组等,memset使用例如std::string(对于上述情况),std::vectorstd::array

于 2012-10-17T13:47:06.090 回答
1

从 C++ 11 开始,我会选择:

#include <array>

std::array<char, ARRAY_LENGTH> buffer{ '\0' };

buffer.fill('\0');
于 2018-07-29T01:23:11.677 回答
0

Option 3: memset( buffer, '\0', ARRAY_LENGTH ):只会给你数组的长度,但实际上这个参数是总共有多少字节的内存。

Option 1: memset( buffer, '\0', sizeof(buffer) ):会给你错误的答案,因为,bufferchar*sizeof(buffer)不会给你整个数组的大小,只有指针变量的大小。

选项2是对的。

于 2012-10-17T13:48:13.947 回答
0

好吧,我个人喜欢选项3:

memset( buffer, '\0', ARRAY_LENGTH )

ARRAY_LENGTH正是我想填补的记忆。

于 2018-07-28T23:49:03.617 回答