如何使用 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 这很有趣。我以前从未听说过。
当一个简单的循环可以转换为例如memcpy
或 memset
。匹配特定于平台的函数不太常见,但一些编译器确实实现了它。即使您的编译器不这样做,这个循环也是自动向量化的绝佳候选者。【参考方案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 值的缓冲区? [复制]的主要内容,如果未能解决你的问题,请参考以下文章