这个问题遵循前一个关于定义的问题memcpy(0, 0, 0)
,该问题最终被确定为未定义的行为.
正如相关问题所示,答案取决于C11第7.1.4:1条的内容
除非在以下详细说明中另有明确说明,否则以下每个语句均适用:如果函数的参数具有无效值(例如函数域外的值,或程序地址空间外的指针,或空指针,[...])行为未定义.[...]
标准函数memcpy()
需要指向void
和const void
,如下所示:
void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
Run Code Online (Sandbox Code Playgroud)
这个问题值得一问的,只是因为有很多标准的"有效"指针两个概念都:有可以有效地通过指针算术来获得,并且可以有效地相比指针<
,>
同一对象内部其他指针.并且有一些指针可用于解除引用.前一类包括"一个过去"指针,例如&a + 1
和&b + 1
下面的代码片段,而后一个类不包括这些指针有效.
char a;
const char b = '7';
memcpy(&a + 1, &b + 1, 0);
Run Code Online (Sandbox Code Playgroud)
如果将上述片段视为已定义的行为,memcpy()
则根据void
无论如何将参数键入为指针的事实,因此其各自有效性的问题不能解除对它们的解除引用.还是应该&a + 1
和&b + 1
被认为是"程序的地址空间之外"?
这对我很重要,因为我正在使标准C函数的效果正式化.我写的一个先决条件memcpy()
是requires \valid(s1+(0 .. n-1));
,直到有人指出我的注意,GCC 4.9已经开始积极优化这样的库函数调用超出了公式中表示上述( …