有两种方法可以将整数/浮点数组清零:
memset(array, 0, sizeof(int)*arraysize);
或:
for (int i=0; i <arraysize; ++i)
array[i]=0;
显然,对于大型arraysize
,memset更快。但是,在什么时候memset的开销实际上大于for循环的开销?例如,对于大小为5的数组 - 哪个最好?第一个,第二个,甚至可能是未展开的版本:
array[0] = 0;
array[1] = 0;
array[2] = 0;
array[3] = 0;
array[4] = 0;
答案 0 :(得分:45)
很可能,memset()将由编译器内联(大多数编译器将其视为'内在',这基本上意味着它是内联的,除非可能是最低优化或除非明确禁用)。
例如,这里有一些release notes from GCC 4.3:
块移动的代码生成 (
memcpy
)和块集(memset
) 被改写了。海湾合作委员会现在可以选择 最佳算法(循环,展开循环, 带有rep前缀或a的指令 库调用)基于的大小 被复制的块和CPU正在 优化的。一个新选择-minline-stringops-dynamically
有 已被添加。使用此选项字符串 未知大小的操作是 扩大了这样的小块 由内联代码复制,而for 大块使用库调用。 这导致代码比-minline-all-stringops
当 库实现是有能力的 使用缓存层次结构提示。该 启发式选择特定的 算法可以通过覆盖-mstringop-strategy
。最近也是 不同于0的memset
值是 内联。
编译器可能会使用您提供的替代示例执行类似操作,但我敢打赌它不太可能。
它是grep
- 能够一眼就能看出启动的目的是什么(不是说环路特别难以理解)。
答案 1 :(得分:21)
正如迈克尔已经注意到的那样,gcc和我猜其他大多数编译器已经很好地优化了这一点。例如gcc将其转为
char arr[5];
memset(arr, 0, sizeof arr);
到
movl $0x0, <arr+0x0>
movb $0x0, <arr+0x4>
它没有比那更好......
答案 2 :(得分:8)
没有测量就无法回答这个问题。它完全取决于编译器,cpu和运行时库实现。
memset()可能有点“代码味道”,因为它可能容易出现缓冲区溢出,参数反转,并且具有仅清除“逐字节”的不幸能力。然而,可以肯定的是,除了极端情况外,它将“最快”。
我倾向于使用宏来包装它以避免一些问题:
#define CLEAR(s) memset(&(s), 0, sizeof(s))
这可以避开尺寸计算并消除交换长度和值的参数问题。
简而言之,使用memset()“引擎盖下”。写下你想要的,让编译器担心优化。大多数人都非常擅长。
答案 3 :(得分:1)
考虑到这个代码本身就已经被告知了。但是如果你在它的程序中考虑它,我不知道什么,可以做其他事情。例如,如果要每隔一段时间执行此代码以清除数组,则可以运行一个线程,该线程不断地分配一个新的零元素数组,该元素分配给全局变量,当需要清除数组时,代码就是你的代码,只是指向。
这是第三种选择。当然,如果您计划在具有至少两个内核的处理器上运行代码,这是有道理的。此外,代码必须运行多次才能看到好处。对于一次性运行,您可以声明一个填充零的数组,然后在需要时指向它。
希望这可以帮助某人