'--p'如何在for(p =&(* L).elem [(* L).length-1]; p> = q;-p)中工作?

时间:2019-09-22 10:01:59

标签: c++ c loops for-loop decrement

我正在尝试调试以下代码:

Status ListInsert_Sq(SqLIst *L, int i, LElemType_Sq e)
{
    LElemType_Sq *newbase;
    LElemType_Sq *p, *q;

    if(i<1 || i>(*L).length+1)
        return ERROR;                   
    if((*L).length >= (*L).listsize)
    {
        newbase = (LElemType_Sq*)realloc(LElemType_Sq *)realloc((*L).elem, ((*L).listsiz+LISTINCREMENT)*sizeof(LElemType_Sq));
        if(!newbase)
            exit(OVERFLOW);

        (*L).elem = newbase;
        (*L).listsize += LISTINCREMENT; 
     } 

     q = &(*L).elem[i-1];
     for(p=&(*L).elem[(*L).length-1];p>=q;--p)
        *(p+1) = *p;

    *q = e;
    (*L).length++;

    return OK;
} 

这里使用--p是否正确? 具体来说,我想知道列表的最后一个元素是否将被上一个元素移动或覆盖?

谢谢!

2 个答案:

答案 0 :(得分:1)

此代码(在其中添加了缺失的分号):

for(p=&(*L).elem[(*L).length-1];p>=q;--p)
    *(p+1) = *p;

p设置为指向数组elem中最后分配的元素。然后*(p+1) = *p;将最后一个设置的元素复制到上面新分配的空间(与realloc分配)。 (“分配的元素”是指已为其分配值的元素。)

然后--p递减指针以指向上一个元素。 (对指针使用算术以数组元素为单位。)然后*(p+1) = *p;将倒数第二个分配的元素复制到最后一个分配的元素的前一个空间。然后循环以这种方式继续,有效地将每个元素沿数组向上移动了一个空间。

最终,当索引为i-1的元素被移动时,循环似乎打算停止,因为q被设置为带有q = &(*L).elem[i-1];的元素的地址。

但是,它是有缺陷的。如果i为1,则q指向数组的第一个元素,p最终将到达该元素,而--p将尝试递减{{1}指向数组开始之前的位置。这种尝试的行为不是由C标准定义的。 (假定p指向数组的开头。很可能L指向数组的开头以外的位置,在这种情况下不会发生此问题。)

答案 1 :(得分:1)

重写后,代码的猜测意图如下:


#include <stdlib.h>
#include <string.h>
#include "listmeuk.h"

Status ListInsert_Sq(SqLIst *lp, int index, LElemType_Sq elem)
{
    if(index<1 || index>lp->length+1) return ERROR; // this assumes 1-based indexing
    index--; // transform to zero-based indexing

    if(lp->length >= lp->listsize)
    {
        LElemType_Sq *newbase;
        newbase = realloc(lp->elem, (lp->listsiz+LISTINCREMENT) *sizeof *newbase);
        if(!newbase) exit(OVERFLOW);

        lp->elem = newbase;
        lp->listsize += LISTINCREMENT; 
     } 

    if(index < lp->length) memmove(&(lp->elem[index+1]), &(lp->elem[index]), (lp->length-index) * sizeof lp->elem[0] );

    lp->elem[index] = elem;
    lp->length++;

    return OK; 

}