简体   繁体   English

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

[英]How to memset char array with null terminating character?

What is the correct and safest way to memset the whole character array with the null terminating character?用空终止字符 memset 整个字符数组的正确和最安全的方法是什么? I can list a few usages:我可以列出一些用法:

...
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 );
...
  • Does any of these have significant advantage over other(s)?这些中的任何一个比其他的有显着优势吗?
  • What kind of issues can I face with with usages 1, 2 or 3?用法 1、2 或 3 会遇到什么样的问题?
  • What is the best way to handle this request?处理此请求的最佳方法是什么?

Options one and two are just wrong.选项一和二是错误的。 The first one uses the size of a pointer instead of the size of the array, so it probably won't write to the whole array.第一个使用指针的大小而不是数组的大小,因此它可能不会写入整个数组。 The second uses sizeof(char*) instead of sizeof(char) so it will write past the end of the array.第二个使用sizeof(char*)而不是sizeof(char)所以它会写到数组的末尾。 Option 3 is okay.选项3没问题。 You could also use this你也可以用这个

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

but sizeof(char) is guaranteed to be 1.sizeof(char)保证为 1。

The idiomatic way is value-initializing the array:惯用的方法是对数组进行值初始化:

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

Option 1 only sets the first sizeof(char*) bytes to 0, or runs into undefined behavior if ARRAY_LENGTH < sizeof(char*) .选项 1仅将第一个sizeof(char*)字节设置为 0,或者如果ARRAY_LENGTH < sizeof(char*)未定义的行为。 This is due to using the size of the pointer instead of the size of the type.这是由于使用指针的大小而不是类型的大小。

Option 2 runs into undefined behavior because you're attempting to set more than ARRAY_LENGTH bytes.选项 2遇到未定义的行为,因为您试图设置超过 ARRAY_LENGTH 个字节。 sizeof(char*) is almost certainly greater than 1. sizeof(char*)几乎肯定大于 1。

Since this is C++ though (no new in C), I suggest you use a std::string instead.由于这是 C++(C 中没有new内容),我建议您改用std::string

For C (assuming malloc instead of new[] ), you can use对于 C(假设malloc而不是new[] ),您可以使用

memset( buffer, 0, ARRAY_LENGTH );

Since the question keeps changing, I define:由于问题不断变化,我定义:

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

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

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

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

If the question is merely, "what is the correct way to call memset " rather than "what is the best way to zero this array", then either 2b or 3 is correct.如果问题仅仅是“调用memset的正确方法是什么”而不是“将此数组置零的最佳方法是什么”,那么 2b 或 3 是正确的。 1 and 2a are wrong. 1和2a是错误的。

You can have a style war over 2b vs 3: whether to include the sizeof(char) or not -- some people leave it out because it's redundant (I usually do), other people put it in to create a kind of consistency with the same code setting an array of int .您可以针对 2b 与 3 进行风格大战:是否包含sizeof(char)或不包含它——有些人将其删除是因为它是多余的(我通常这样做),其他人将其添加是为了与相同的代码设置一个int数组。 That is to say they always multiply a size by a number of elements, even though they know the size is 1. One possible conclusion is that the "safest" way to memset the array pointed to by buffer is:也就是说,它们总是将一个大小乘以多个元素,即使它们知道大小为 1。一个可能的结论是,对buffer指向的数组进行 memset 的“最安全”方法是:

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

This code remains correct if the type of buffer changes, provided of course that it continues to have ARRAY_LENGTH elements of whatever type that is, and provided that all-bits-zero remains the correct initial value.如果缓冲区的类型发生变化,此代码将保持正确,当然前提是它继续具有任何类型的ARRAY_LENGTH元素,并且前提是全零位保持正确的初始值。

Another option beloved of "C++ is not C" programmers, is: “C++ 不是 C”程序员钟爱的另一个选择是:

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

If you care, you can then check for yourself whether or not your compiler optimizes this to the same code to which it optimizes the equivalent call to std::memset .如果您关心,您可以自己检查您的编译器是否将其优化为与它优化对std::memset的等效调用相同的代码。

char *buffer = new char [ARRAY_LENGTH](); is nifty but almost useless in C++ in practice because you pretty much never allocate an array with new in the first place.很漂亮,但实际上在 C++ 中几乎没用,因为您几乎从不首先使用new分配数组。

std::string buffer(ARRAY_LENGTH, 0); introduces a particular way of managing the buffer, which may or may not be what you want but often is.引入了一种管理缓冲区的特定方法,这可能是也可能不是您想要的,但通常是。 There's a lot to be said for char buffer[ARRAY_LENGTH] = {0}; char buffer[ARRAY_LENGTH] = {0}; in some cases.在某些情况下。

  • Does any of these have significant advantage over other(s)?这些中的任何一个比其他的有显着优势吗?
  • What kind of issues can I face with with usages 1, 2 or 3?用法 1、2 或 3 会遇到什么样的问题?

1st is wrong, because sizeof(buffer) == sizeof(char*) .第一个是错误的,因为sizeof(buffer) == sizeof(char*)

2nd and 3rd are OK.第二个和第三个都可以。

  • What is the best way to handle this request?处理此请求的最佳方法是什么?

Why not just:为什么不只是:

buffer[0] = '\0';

If this is a char array, why bother with the rest of the characters?如果这是一个char数组,为什么还要考虑其余的字符呢? With the first byte set to zero, you have the equivalent of "" in your buffer .将第一个字节设置为零后,您的buffer中就有了等同于""的内容。

Of course, if you really insist on having all of buffer zeroed, use the answer with std::fill - this is the proper way.当然,如果您真的坚持将所有buffer清零,请使用std::fill的答案——这是正确的方法。 I mean std::fill(buffer, buffer + ARRAY_LENGTH, 0);我的意思是std::fill(buffer, buffer + ARRAY_LENGTH, 0); . .

If you absolutely must use a raw array in C++ (it's a very ungood idea), do it like this:如果您绝对必须在 C++ 中使用原始数组(这是一个非常糟糕的主意),请这样做:

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

For C++ memset is generally the last refuge of the incompetent, although I learned within the last few months that for acceptable performance, with current tools, it's necessary to go down to that level when one implements one's own string class.因为 C++ memset通常是无能者的最后避难所,尽管我在过去几个月内了解到,为了获得可接受的性能,使用当前的工具,当一个人实现自己的字符串类时,有必要降低到那个级别。

Instead of these raw arrays etc., which can appear to need memset , use eg std::string (for the above case), std::vector , std::array etc.使用例如std::string (对于上述情况)、 std::vectorstd::array等,而不是这些看起来需要memset的原始数组等。

Since C++ 11, I whould choose:从 C++ 11 开始,我会选择:

#include <array>

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

buffer.fill('\0');

Option 3: memset( buffer, '\0', ARRAY_LENGTH ): will give you only length of array but actually this parameter is total how much byte of memory. Option 3: memset( buffer, '\0', ARRAY_LENGTH ):只会给你数组的长度,但实际上这个参数是内存的总字节数。

Option 1: memset( buffer, '\0', sizeof(buffer) ): will give you wrong answer because, buffer is char* . Option 1: memset( buffer, '\0', sizeof(buffer) ):会给你错误的答案,因为bufferchar* sizeof(buffer) would not give you size of whole array only size of a pointer variable. sizeof(buffer)不会给你整个数组的大小,只有指针变量的大小。

Option 2 is right.选项2是对的。

Well, personally I like option 3:好吧,我个人喜欢选项 3:

memset( buffer, '\0', ARRAY_LENGTH )

ARRAY_LENGTH is exactly what I would like to fill in the memory. ARRAY_LENGTH正是我想填入内存的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM