如何使用 memset 初始化具有非 0 值的缓冲区? [复制]

Posted

技术标签:

【中文标题】如何使用 memset 初始化具有非 0 值的缓冲区? [复制]【英文标题】:How to use memset for initializing bufffers with values other than 0? [duplicate] 【发布时间】:2014-01-06 13:47:57 【问题描述】:
int buff[1000] 
memset(buff, 0, 1000 * sizeof(int));

将用o初始化buff

但以下不会用 5 初始化 buff。那么在 C 中(而不是在 C++ 中)使用 memset 来实现这一点的方法是什么?我想为此目的使用 memset。

int buff[1000] 
memset(buff, 5, 1000 * sizeof(int));

【问题讨论】:

buff的类型是什么? 什么是buff数据类型,是整数吗? memset 将每个字节设置为指定值。如果您对多字节数据类型进行操作,则不能使用memset 将它们设置为任意值。 这不是链接问题的完全重复,因为该问题是针对 C++ 的(正确的做法是使用 std::fill_n)。这个问题是针对C的,答案不一样。 【参考方案1】:

memset 将字节而不是数据类型初始化为一个值。所以对于你的例子......

int buff[1000] 
memset(buff, 5, 1000 * sizeof(int));

...如果int 是四个字节,则所有四个字节都将初始化为5。每个整数实际上将具有0x05050505 == 84215045 的值,而不是您所期望的5

如果您想将数组中的每个整数初始化为 5,您必须这样做:

int i;
for(i = 0; i < 1000; i++)
    buff[i] = 5;

【讨论】:

当针对具有优化填充实现的平台(来自 Paul R 的答案的 memset_pattern4)时,编译器甚至可以选择将此循环优化为对该函数的调用。 @StephenCanon 这很有趣。我以前从未听说过。 当一个简单的循环可以转换为例如memcpymemset。匹配特定于平台的函数不太常见,但一些编译器确实实现了它。即使您的编译器不这样做,这个循环也是自动向量化的绝佳候选者。【参考方案2】:

根据您使用的操作系统,您可能可以使用memset_pattern4 et al,否则您只需使用循环即可。

【讨论】:

【参考方案3】:

我个人不建议将memset 用于一般初始化。您必须确保能够正确和便携地使用它的事情太多了。它基本上只适用于char 数组或微控制器代码。

C中初始化数组的方式如下(假设大小N):

for (i = 0; i < N; ++i)
    buff[i] = init_value;

使用 C99,您可以做更多有趣的事情。例如,假设缓冲区是以下结构的数组:

struct something

    size_t id;
    int other_value;
;

然后你可以这样初始化:

for (i = 0; i < N; ++i)
    buff[i] = (struct something)
        .id = i
    ;

这称为指定初始化程序。像所有其他初始化器情况一样,如果您不提及结构的特定字段,它将自动为零初始化。

【讨论】:

【参考方案4】:

如果 buff 不是字节数组,则只能使用 memset 将其初始化为由重复的十六进制值组成的值(例如 -1、0x01010101 等)

一种方法是使用memcpy,因此:

buff[0] = 5;
memcpy(buff + 1, buff, sizeof(buff) - sizeof(*buff))

但是这依赖于未定义的行为,可能会或可能不会在您的系统上运行。

一个体面的编译器应该产生一个足够高效的循环

for (i = 0; i < 1000; i++) buff[i] = 5;

【讨论】:

我不知道建议的memcpy技巧确实“工作”的任何现代系统。 我不认为故意建议未定义的行为是可以的 @Shahbaz 取决于他的系统如何工作以及他对优化的渴望程度。我也不建议 memset 填充数组,因为不清楚 @TomTanner,一个设置元素的简单for循环可以像memcpy一样优化。请注意,memcpy 需要 restrict 指向源和目标的指针。这意味着(粗略地说)优化器可以假设它们不重叠并相应地进行优化。如果你给它重叠的内存区域,即使你的答案是“更优化”,它也是不正确的。 我意识到一个体面的编译器可以生成在 memset 优化的代码。但请相信我,我在各个地方都遇到过很多像 memcpy 这样的代码。如果OP不走运,他们会这样做。假设我应该反过来说。

以上是关于如何使用 memset 初始化具有非 0 值的缓冲区? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

使用 memset 将派生结构归零

在JAVA中有没有象C语言里的memset函数

memset 初始化数组 & 实现原理

C++如何定义操作符[]来读写循环缓冲区的一项

数组的初始化与memset的注意事项

加入后如何删除具有非空值的重复列? [复制]