指针行为

时间:2015-07-06 09:29:27

标签: c

此程序要求用户填写表格并询问他要删除的值,然后创建没有值的新表

#include<stdio.h>
#include<stdlib.h>

main()
{
int *tab;
int *p1,*p2;
int nb,val,i;

printf("Number of values for the table ? ");
scanf("%d",&nb);

tab=(int*)malloc(nb*sizeof(int)); // on alloue le nombre de cases demandees au tableau

for (i=0;i<nb;i++)
    {
    printf("value n %d of the table? ",i);
    scanf("%d",&tab[i]);
    }

printf("\n value to delete of the table ? ");
scanf("%d",&val);

p1=tab; // on fait pointer p1 s ur la premiere case du tableau
p2=tab; // idem pour p2

// p1 va parcourir le tableau tout entier
// p2 n'avancera que si l'element du tableau en cours est different de val

while (p1<tab+nb) // tant qu'on n'est pas a la fin du tableau
    {
    if (*p1!=val) // si l'element en cours est different de val
        {
        *p2=*p1; // on recopie l'element dans la case pointee par p2
        p2++;   // on incremente p2 pour passer a la case suivante
        }
    p1++;
}

for (i=0;i<*p2-*tab;i++) // p2-tab= nombre de cases encore remplies
    {
    printf("value n %d of the table : %d\n",i,tab[i]);
    }

}

我不明白为什么最后一个for循环也可以这样写?

for (i=0;i<p2-tab;i++)

它不应该返回地址的值,只返回地址

1 个答案:

答案 0 :(得分:2)

for (i=0;i<*p2-*tab;i++)暴露undefined behaviour,无论如何它在语义上都是错误的。

正确的代码是:

for (i=0;i<p2-tab;i++)
{
    printf("value n %d of the table : %d\n",i,tab[i]);
}

i用作tabtab[i])中的索引,p2指向元素等于{后的数组的最后一个元素之后的第一个元素{1}}被删除了。 val是删除后数组中元素的数量,这是为了打印剩余数字而执行的正确迭代次数。

为什么p2-tab错了?

从语义的角度来看,for (i=0;i<*p2-*tab;i++)*p2是数组中的两个元素(忽略*tab超出数组边界的情况,我们将讨论它两个以下段落。

因此,*p2是一些随机数,甚至可能是负数。将它用作数组上的迭代次数没有任何意义。

从语言的角度来看,如果数组的初始内容中不存在*p2-*tab,则在“删除”后,val等于p2。但是tab+nb指向一个分配的内存块,它可以容纳最多tab个值,这意味着nb在这个内存块之外。

这使得代码具有undefined behaviour,这意味着任何事情都可能发生;有时它运行得很好;大多数时候它会产生意想不到的结果;根据操作系统和编译器的实现,它还可以生成未处理的异常,并由操作系统终止。