如何用空终止字符memset char数组?

时间:2012-10-17 13:43:43

标签: c++ arrays c++11 memset null-terminated

使用null终止字符memset整个字符数组的正确和最安全的方法是什么?我可以列出一些用法:

...
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 );
...
  • 其中任何一项都有明显的优势吗?
  • 使用1,2或3时,我可以面对哪些问题?
  • 处理此请求的最佳方法是什么?

8 个答案:

答案 0 :(得分:20)

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

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

sizeof(char)保证为1。

答案 1 :(得分:13)

惯用的方法是初始化数组:

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

选项1 仅将第一个sizeof(char*)字节设置为0,或者在ARRAY_LENGHT < sizeof(char*)时遇到未定义的行为。

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

由于这是C ++(C中没有new),我建议您改用std::string

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

memset( buffer, 0, ARRAY_LENGTH );

答案 2 :(得分:5)

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

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 vs 3的风格大战:是否要包括sizeof(char) - 有些人因为冗余(我通常会这样做)而将其排除在外,其他人则将其用于创建一种类型与设置int数组的相同代码的一致性。也就是说,它们总是将大小乘以一些元素,即使它们知道大小为1.一个可能的结论是,buffer指向的memset数组的“最安全”方式是:

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

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

“C ++不是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};有很多话要说。

答案 3 :(得分:3)

  
      
  • 这些中的任何一个都有明显的优势吗?
  •   
  • 使用1,2或3时,我可以面对哪些问题?
  •   

1st错了,因为sizeof(buffer) == sizeof(char*)

第二和第三是好的。

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

为什么不呢:

buffer[0] = '\0';

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

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

答案 4 :(得分:2)

如果你绝对必须在C ++中使用原始数组(这是一个非常不好的想法),那就这样做:

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

对于C ++而言,memset通常是无能的最后避难所,尽管我在过去几个月内了解到,对于可接受的性能,使用当前的工具,当一个人实现自己的字符串时,有必要降低到那个级别。类。

代替这些看似需要memset的原始数组等,例如使用std::string(针对上述情况),std::vectorstd::array等。

答案 5 :(得分:1)

自C ++ 11起,我应该选择:

#include <array>

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

buffer.fill('\0');

答案 6 :(得分:0)

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

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

选项2是对的。

答案 7 :(得分:0)

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

memset( buffer, '\0', ARRAY_LENGTH )

ARRAY_LENGTH正是我要填写的内容。