我可以将“字节数”设置为零的memcpy()和memmove()吗?


102

当我无力移动/复制时,是否需要将案件作为memmove()/ memcpy()边缘案件

int numberOfBytes = ...
if( numberOfBytes != 0 ) {
    memmove( dest, source, numberOfBytes );
}

还是应该不检查就调用函数

int numberOfBytes = ...
memmove( dest, source, numberOfBytes );

前段中的支票是否必要?


6
这个问题使我想起了一些检查诸如free之类的函数的空指针的问题。没必要,但是我会在此处发表评论以表明您对此的想法。
蟾蜍

12
@Toad:除了使代码混乱之外,还有什么用?在阅读某人的代码时,我不需要知道原始程序员“是在考虑执行此操作,而这实际上不是必需的,但是因为它是不必要的,所以我没有这样做”。如果我看到释放了一个指针beeing,我知道它可以为空,所以我不需要知道原始程序员关于“我应该检查空”的想法。使用memcpy
jalf 2010年

8
@jalf:这是关于stackoverflow的问题,这使人们感到怀疑。因此,添加评论可能无济于事,但可能会帮助知识较少的人
Toad

2
@Toad是的,原则上明确指出为什么实际上没有必要进行检查的评论很有价值。硬币的另一面是,该特定示例是一个常见情况,涉及一个标准库函数,每个程序员只需要学习一次答案即可。然后他们可以在阅读的任何程序中识别出不需要进行这些检查。对于那个原因,我省略了意见。一个具有多个调用的代码库要么需要将注释复制并粘贴到每个注释,要么仅在某些调用上随意使用它们,这两个调用都很丑陋。
Mark Amery

Answers:


145

根据C99标准(7.21.1 / 2):

如果声明为as的参数size_t n指定函数数组的长度,则对该函数n的调用的值可以为零。除非在本节中对特定功能的描述中另有明确说明,否则此类调用上的指针参数仍应具有有效值,如7.1.4中所述。在这样的调用中,找不到字符的函数没有出现,比较两个字符序列的函数返回零,而复制字符的函数则复制零字符。

所以答案是否定的。不需要检查(或者是;您可以通过零)。


1
如果指针指向数组最后一个元素之后的位置,那么出于该功能的目的,该指针是否被视为“有效”?不能合理地引用这样的指针,但是可以安全地做一些其他类似指针的事情,例如从中减去一个。
supercat

1
@supercat:是的,一个指向数组末尾的指针与该数组内的其他指针(或指向数组末尾的指针)一起进行指针算术有效,但不可取消引用。
Mike Seymour

@MikeSeymour:引用不应该暗示相反的答案:检查是必要的,并且不能使用空指针传递零吗?
neverhoodboy 2014年

7
@neverhoodboy:不,引号清楚地表明“ n可以具有零值”。您是正确的,您不能传递空指针,但这不是问题所在。
Mike Seymour 2014年

1
@MikeSeymour:我的错。真对不起。问题是关于大小而不是指针。
neverhoodboy 2014年

5

正如@You所说,该标准指定memcpy和memmove应该可以毫无问题地处理这种情况。因为它们通常以某种方式实现

void *memcpy(void *_dst, const void *_src, size_t len)
{
    unsigned char *dst = _dst;
    const unsigned char *src = _src;
    while(len-- > 0)
        *dst++ = *src++;
    return _dst;
}

除了函数调用之外,您甚至不应有任何性能损失;如果编译器支持此类函数的内在函数/内联,则额外的检查甚至可能使代码的运行速度稍慢一些,因为该检查已经在进行。


1
我认为此功能可能是在汇编程序中完成的,您可以在其中优化内存传输,这比在c语言中要好得多
Toad

“有点像” :)实际上,我见过的几乎所有实现都是在汇编中的,并尝试使用本机字长(例如x86上的uint32_t)复制大多数位,但这并没有改变答案的实质。 :这是一个while循环,在开始之前不需要大量的计算,因此检查已经完成。
Matteo Italia 2010年

9
-1,典型的实现与用零参数调用这些函数(甚至可能没有实现为C函数)是否有效的C无关。
R .. GitHub停止帮助ICE,2010年

4
正如我在回答之初所说的那样,其他答案已经涵盖了它是有效的C的事实:“正如@You所说,该标准指定memcpy和memmove应该毫无问题地处理这种情况”。我只是基于以下事实添加了我的观点:出于性能原因,您甚至不必担心用len = 0调用memcpy,因为在这种情况下,这几乎是零成本。
Matteo Italia 2010年
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.