我正在尝试调试以下代码:
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
是否正确?
具体来说,我想知道列表的最后一个元素是否将被上一个元素移动或覆盖?
谢谢!
答案 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;
}