在刚过数组末尾的指针上调用长度为零的memcpy合法吗?
同样,使用无效或在刚过数组末尾的指针上调用长度为零的memcpy合法吗?,c,pointers,language-lawyer,undefined-behavior,C,Pointers,Language Lawyer,Undefined Behavior,同样,使用无效或NULL指针调用memcpy等函数是未定义的行为,即使length参数为零。在这种函数的上下文中,尤其是memcpy和memmove,刚刚超过数组末尾的指针是有效指针吗 我问这个问题是因为刚过数组末尾的指针是合法获取的(与之相反,例如,一个指针超过数组末尾的两个元素),但不允许取消引用它,然而ISO 9899:2011的脚注106指出,这样的指针指向程序的地址空间,根据§7.1.4,指针有效所需的标准 这种用法出现在我想将一个项插入数组中间的代码中,要求我在插入点之后移动所有项:
NULL
指针调用memcpy
等函数是未定义的行为,即使length参数为零。在这种函数的上下文中,尤其是memcpy
和memmove
,刚刚超过数组末尾的指针是有效指针吗
我问这个问题是因为刚过数组末尾的指针是合法获取的(与之相反,例如,一个指针超过数组末尾的两个元素),但不允许取消引用它,然而ISO 9899:2011的脚注106指出,这样的指针指向程序的地址空间,根据§7.1.4,指针有效所需的标准
这种用法出现在我想将一个项插入数组中间的代码中,要求我在插入点之后移动所有项:
void make_space(type *array, size_t old_length, size_t index)
{
memmove(array + index + 1, array + index, (old_length - index) * sizeof *array);
}
如果要在数组末尾插入,索引
等于长度
和数组+索引+1
点刚好超过数组末尾,但复制的元素数为零。如果查看
7.21.1.p2
其中声明为size\u t n的参数指定
数组中,n可以在调用该函数时具有值零
功能。除非说明书中另有明确规定
此子类中的特定函数,指针参数
调用仍应具有有效值,如7.1.4所述。就这样
调用时,查找字符的函数不会找到任何匹配项
比较两个字符序列的函数返回零,而
复制字符的函数复制零个字符。
7.21.2.1
7.1.4.p1
。。。如果函数参数被描述为数组,则指针
实际传递给函数的值应为all
处理计算和对象访问(如果
指针确实指向这样一个数组的第一个元素)中
事实有效
重点补充。似乎指针必须指向有效的位置(在去引用的意义上),而关于指针算术允许指向末尾+1的段落在这里不适用
问题在于memcpy
的参数是否为数组。当然,它们不是声明为数组,而是
7.21.1.p1表示
header string.h声明了一个类型和几个函数,以及
定义一个宏,该宏用于操作字符类型和
其他被视为字符类型数组的对象
并且memcpy
在string.h中。因此,我假设
memcpy
确实将参数视为字符数组。
因为所提到的宏是
NULL
,所以句子中的“有益于…”部分显然适用于函数。将结束指针传递给memmove
的第一个参数有几个陷阱,可能会导致鼻恶魔攻击。
严格地说,没有不透水的保证可以很好地定义
(不幸的是,标准中没有太多关于“超过最后一个元素”的信息。)
注意:很抱歉现在有另一个方向
基本的问题是,如果移动了0个字节,则“结束指针后的一个”是否是memmove
的有效第一个函数参数:
T array[length];
memmove(array + length, array + length - 1u, 0u);
所讨论的要求是第一个论点的有效性
N1570,7.1.4,1
如果函数参数被描述为数组,则实际传递给函数的指针的值应确保所有地址计算和对对象的访问(如果指针确实指向该数组的第一个元素,则该值将是有效的)实际上都是有效的
如果函数的参数具有无效值(例如函数域外的值,或程序地址空间外的指针,或空指针,或对应参数不符合常量条件时指向不可修改存储的指针)或类型(升级后)参数个数可变的函数不需要该行为,但该行为未定义
如果指针
int a ;
int* p = a+1 ;