清除char数组c


104

我认为通过将第一个元素设置为null会清除char数组的全部内容。

char my_custom_data[40] = "Hello!";
my_custom_data[0] = '\0';

但是,这只会将第一个元素设置为null。

要么

my_custom_data[0] = 0; 

而不是使用memset,我认为上述2个示例应清除所有数据。


1
Jared,为什么要设置c ++标签?他谈到了“ C”,没有添加任何与C ++相关的标签。
Johannes Schaub-litb

1
即使他没有指定,这同样适用于C ++中的字符数组。
亚当·霍斯

4
我已删除了C ++标签,以避免我们在提供C ++特定解决方案的人们中看到的东西
Alnitak

Answers:


113

这取决于您如何查看阵列。如果将数组视为一系列字符,则清除数据的唯一方法是触摸每个条目。memset可能是实现此目标的最有效方法。

另一方面,如果您选择将其视为C / C ++空终止的字符串,则将第一个字节设置为0将有效清除该字符串。


4
他们在答案中的关键词是“有效”。只有第一个元素开始设置为0,其余元素仍具有未定义的值,但是如果将数组视为以空终止的字符串,并且第一个元素为null,则该字符串被视为空。
阿诺德·斯彭斯

的确,这就是乡亲们的答案。
Johannes Schaub-litb

完全是@caparcode。这就是为什么了解如何使用数组非常重要。
JaredPar

是的,这就是我在第一篇文章中应该说的。字符是终止的字符串。所以这些都可以做到。char [0] ='\ 0'; 或char [0] =0。我不确定,但我听说使用'\ 0'对于使用以null终止的字符串更好。
ant2009年

@robUK,是的,您是正确的。从技术上讲,'\ 0'等于0(以ascii表示),但是您应该使用'\ 0',因为它可以使您的意图清楚
Mark Testa'3

70

C语言中的数组只是一个内存位置,因此,实际上,您的my_custom_data[0] = '\0';分配只是将第一个元素设置为零,而其他元素则保持不变。

如果要清除数组中的所有元素,则必须访问每个元素。那memset是为了:

memset(&arr[0], 0, sizeof(arr));

通常,这是解决此问题的最快方法。如果可以使用C ++,请考虑使用std :: fill代替:

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);

1
我相信第二个版本应该是:std :: fill(arr,arr + sizeof(arr)/ sizeof(arr [0]),0);
大卫·罗德里格斯(DavidRodríguez)-德里贝斯2009年

说明:不要将sizeof与fill一起使用,因为稍后会遇到int,long,double或有什么问题的数组。
Zan Lynx

我更喜欢:std :: fill(&arr [0],&arr [arr_len],0);
Zan Lynx

Zan Lynx,这是未定义的行为。您不能&arr [arr_len]。但是你必须要做std :: fill(arr,arr + sizeof arr,0); 或者如果您的长度在某处std :: fill(arr,arr + arr_len,0); 假设有一个字符数组
Johannes Schaub-litb

仅在C中有效。尽管该问题明确针对C(另一个人添加了C ++标记,但我不知道为什么),但std :: fill显示了C ++亲和力:)
Johannes Schaub-litb

25

您为什么认为设置单个元素会清除整个数组?特别是在C语言中,如果没有程序员对其进行显式编程,几乎不会发生任何事情。如果将第一个元素设置为零(或任何值),则说明您已经做到了,仅此而已。

初始化时,可以将数组设置为零:

char mcd[40] = {0}; /* sets the whole array */

否则,除了memset或类似的东西,我不知道其他任何技术。


我想这取决于您使用的编译器
cocoafan 2011年

1
@cocoafan:不,它与编译器无关。它是语言规范的一部分。任何行为不同的编译器都不会遵循C语言。
abelenky 2011年

我不知道,谢谢。我找不到任何可以阅读此特殊情况的资源。最好将它作为书签。
cocoafan 2011年

1
这称为部分初始化。我没有C99规范,但是有两个来源: bit.ly/enBC2m “您不需要初始化数组中的所有元素。如果数组已部分初始化,则未初始化的元素将收到0的值。适当的类型。” bit.ly/f9asHH “如果初始化程序少于数组中的元素,则其余元素会自动初始化为0”
abelenky 2011年

这不适用于已经声明并分配了值的数组吗?
skinnedKnuckles

10

用:

memset(my_custom_data, 0, sizeof(my_custom_data));

要么:

memset(my_custom_data, 0, strlen(my_custom_data));

1
第二个选项(memset(my_custom_data, 0, strlen(my_custom_data));)仅清除到第一个'\ 0',该值可能超出数组末尾。这可能会也可能不会。
brewmanz '18年



6

请在下面找到我在案例1和案例2之后用数组中的数据解释的位置。

char sc_ArrData[ 100 ];
strcpy(sc_ArrData,"Hai" );

情况1:

sc_ArrData[0] = '\0';

结果:

-   "sc_ArrData"
[0] 0 ''
[1] 97 'a'
[2] 105 'i'
[3] 0 ''

情况2:

memset(&sc_ArrData[0], 0, sizeof(sc_ArrData));

结果:

-   "sc_ArrData"
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''

尽管将第一个参数设置为NULL可以解决问题,但建议使用memset


4

不。您要做的只是将第一个值设置为“ \ 0”或0。

如果使用空终止字符串,则在第一个示例中,您将获得模仿您期望的行为,但是仍然设置了内存。

如果要在不使用内存集的情况下清除内存,请使用for循环。


我在for循环上说不。尽量不要编写自己的“改进的”(通常不是)库函数。实际上,memset和memcpy非常特殊,通常会根据有关数据对齐和长度的信息内联到CPU的自定义机器代码中。
Zan Lynx

@Zan OP不想使用memset(也许他是嵌入式的并且没有可用的)。但是是的,内存集通常是高度最佳的,并且可能比for循环更快。
亚当·霍斯

是的,但是他不想使用memset,所以我建议使用for循环。
艾伦(Alan)2009年


2

将空字符写入第一个字符就可以了。如果将其视为字符串,则遵循空终止符的代码会将其视为空字符串,但这与清除数据不同。如果您想真正清除数据,则需要使用memset。



1

我认为通过将第一个元素设置为null可以清除char数组的全部内容。

你发现那是不正确的

但是,这只会将第一个元素设置为null。

究竟!

您需要使用memset清除所有数据,仅将其中一项设置为null是不够的。

但是,如果将数组的元素设置为null意味着特殊的事情(例如,当使用null终止字符串时),将第一个元素设置为null可能就足够了。这样,即使该数组仍在内存中包含旧字符,该数组的任何用户仍将理解它为空


:不要使用“memset的”过度可读性stackoverflow.com/questions/453432/...
约翰Gerell

1

将第一个元素设置为NULL。打印char数组将不会给您任何回报。



-3
void clearArray (char *input[]){
    *input = ' '; 
}

1
这不是清除,只是将第一个字符设置为“”!我认为您想编写* input ='\
0'– stviper

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.