2

我刚刚在我的设置(gcc 4.8.2,最近的 uClibc)上测试了以下内容,它运行良好:

#include <string.h>
int main(int argc, char **argv) {
    char buf[4], fub[4] = "abc";
    memmove(buf, fub, 0);
    memmove(buf, NULL, 0);
    memmove(NULL, fub, 0);
    memmove(NULL, NULL, 0);
    return 0;
}

它也适用于memcpy. 所以很明显,将NULLs 传递给这些函数在实践中可以正常工作,至少在某些设置上是这样。但我想进行防御性编码,并试图确定是否有任何 C 标准允许我依赖这种行为,或者它是未定义的还是实现定义的。

这个答案指出,C99 标准确实指定将 0 的大小传递给这些函数应该是有效的。这是第 7.21.1 节中的文本:

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

另一方面,阅读第 7.1.4 节似乎说NULL未定义传递 s :

除非在随后的详细描述中另有明确说明,否则以下每个语句都适用: 如果函数的参数具有无效值(例如函数域之外的值,或程序地址空间之外的指针,或空指针,或指向不可修改存储的指针(当相应参数不是 const 限定时)或具有可变数量参数的函数不期望的类型(提升后),行为未定义。

这也是你的理解吗?任何人都可以确认/否认该标准是否未定义此行为吗?

我主要针对 C99,但也欢迎有关其他 C 标准的反馈。

4

0 回答 0