int *shiftRmemmove(int *arr, size_t size)
{
    if(arr && size)
    {
        memmove(arr + size - 1, arr + size - 2, (size - 1) *sizeof(*arr));
        arr[0] = 0;
    }
    return arr;
}

如果是size == 1的话有定义吗?它正在计算并传递对数组1*before的元素的引用,第一个元素.相当于:memove(arr, arr -1, 0); (©Jabberwocky)

推荐答案

arr是一个指针,但从注释中我们可以假定它指向某个数组A的元素0.

考虑一下表达式arr + size - 2.arr + size是没有争议的;它指向&A[1],即使A是一个由1个元素组成的数组,因此&A[1]是该数组最后一个元素"后面"的地址.

对于arr + size - 2,实际上是&A[1] - 2,我们认为C 2018 6.5.6 8:

如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向距原始元素的元素偏移量,以便结果数组元素和原始数组元素的下标差等于整数表达式.换言之,如果表达式P指向数组对象的第i个元素,则表达式(P)+N(等价地,第N+(P))和第(P)-N(其中N具有值n)分别指向数组对象的第i+n个和第i个−第n个元素,provided they exist[增加了强调]…

此段落不定义&A[1] - 2的结果,因为索引为−1的数组A的元素不存在.仅此一项就足以呈现未定义的行为,因为标准中没有其他内容对其进行定义,并且C 2018 4 2告诉我们:未定义的行为在本文档…中以其他方式指示因为省略了对行为的任何明确定义.但是,6.5.6 8继续:

…如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象最后一个元素之后的元素,则求值不会产生溢出;否则,行为为未定义的…

在这里,指针操作数(&A[1])和结果(&(A[-1])不指向同一数组对象的元素,也不指向它后面的一个数组对象的元素,因此行为未定义.

arr + size - 2的求值发生在调用memmove之前,因此memmove是否使用其相应的参数是无关紧要的;行为已经未定义.

C++相关问答推荐

如何将匿名VLA分配给指针?

我可以动态分配具有空类型函数的矩阵吗?

通过MQTT/蚊子发送大文件—限制在4MB

在C语言中使用scanf()时我无法理解的警告

Tiva TM4C123GXL的I2C通信

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

在一个小型玩具项目中实现终端历史记录功能

在编译时参数化类型定义

使用AVX2的英特尔2022编译器的NaN问题&;/fp:FAST

Boyer Moore算法的简单版本中的未定义行为

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

使用nmake for程序比Hello World稍微复杂一些

为什么编译器不能简单地将数据从EDI转移到EAX?

我正在try 将QSORT算法实现为C++中的泛型函数

将size_t分配给off_t会产生符号转换错误

如果类型是新的,offsetof是否与typeof一起工作?

在分配内存后使用指针是未定义的行为吗?

使用 GCC 将一个函数中初始化的 struct 体实例通过指针传递到 C 中的另一个函数会产生不同的结果

SSE 向量与 Epsilon 的比较

保存有符号整数结果的变量是否会溢出(后增量的副作用),并且此后从未在任何表达式中使用过它,是否会导致 UB?