c - 在 C 中使用 memset() 有什么好处

标签 c embedded memset

我很好奇在类似于下面的情况下使用 memset() 在效率方面是否有任何优势。

给定以下缓冲区声明...

struct More_Buffer_Info
{
    unsigned char a[10];
    unsigned char b[10];
    unsigned char c[10];
};

struct My_Buffer_Type
{
    struct More_Buffer_Info buffer_info[100];
};

struct My_Buffer_Type my_buffer[5];

unsigned char *p;
p = (unsigned char *)my_buffer;

除了减少代码行数之外,使用它还有一个优势:

memset((void *)p, 0, sizeof(my_buffer));

关于这个:

for (i = 0; i < sizeof(my_buffer); i++)
{
    *p++ = 0;
}

最佳答案

这适用于 memset()memcpy():

  1. 更少的代码:正如您已经提到的,它更短 - 更少的代码行。
  2. 更具可读性:越短通常也越可读。 (memset() 比那个循环更具可读性)
  3. 它可以更快:它有时可以允许更积极的编译器优化。 (所以它可能会更快)
  4. 未对齐:在某些情况下,当您在不支持未对齐访问的处理器上处理未对齐数据时,memset()memcpy () 可能是唯一干净的解决方案。

为了扩展第三点,编译器可以使用 SIMD 等对 memset() 进行大量优化。如果您改为编写循环,编译器将首先需要“弄清楚”它的作用,然后才能尝试对其进行优化。

这里的基本思想是 memset() 和类似的库函数,在某种意义上,“告诉”编译器你的意图。


正如@Oli 在评论中提到的,有一些缺点。我将在这里展开它们:

  1. 您需要确保memset() 确实按照您的要求执行。该标准并未说明各种数据类型的零在内存中必须为零。
  2. 对于非零数据,memset() 仅限于 1 个字节的内容。因此,如果您想将 int 数组设置为零以外的值(或 0x01010101 或其他值),则不能使用 memset() ...)。
  3. 虽然很少见,但在某些极端情况下,您实际上可以使用自己的循环在性能上击败编译器。*

*我将根据我的经验举一个例子:

尽管 memset()memcpy() 通常是编译器内部函数,由编译器进行特殊处理,但它们仍然是 generic 函数。他们只字不提数据类型,包括数据的对齐方式。

因此在少数情况下(虽然很少见),编译器无法确定内存区域的对齐方式,因此必须生成额外的代码来处理未对齐情况。然而,如果您是程序员,100% 确定对齐,那么使用循环实际上可能会更快。

一个常见的例子是使用 SSE/AVX 内在函数。 (例如复制 16/32 字节对齐的 float 数组)如果编译器无法确定 16/32 字节对齐,则需要使用未对齐的加载/存储和/或处理代码。如果您只是使用 SSE/AVX 对齐的加载/存储内在函数编写一个循环,您可能会做得更好。

float *ptrA = ...  //  some unknown source, guaranteed to be 32-byte aligned
float *ptrB = ...  //  some unknown source, guaranteed to be 32-byte aligned
int length = ...   //  some unknown source, guaranteed to be multiple of 8

//  memcopy() - Compiler can't read comments. It doesn't know the data is 32-byte
//  aligned. So it may generate unnecessary misalignment handling code.
memcpy(ptrA, ptrB, length * sizeof(float));

//  This loop could potentially be faster because it "uses" the fact that
//  the pointers are aligned. The compiler can also further optimize this.
for (int c = 0; c < length; c += 8){
    _mm256_store_ps(ptrA + c, _mm256_load_ps(ptrB + c));
}

关于c - 在 C 中使用 memset() 有什么好处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8528590/

相关文章:

c++ - 是否有以相反顺序填充缓冲区的 memset 函数实现?

c - 恢复memset设置的值

c - 创建单位矩阵时出现性能异常

c - 在 OpenCV 中提高相机捕获分辨率

c - 在 C 语言中使用自定义 vector

c - 将多个目标文件链接到二进制 AVR GCC

单声道嵌入式

c++ - 如何在没有任何依赖库的情况下在 Visual Studio 中构建 dll?

c - 将元素添加到结构的数组成员

filesystems - 嵌入式文件系统和断电