减去指针

我被要求描述这些代码行在做大学作业

int main() { int t1[] = {0,0,1,1,1}, t2[] = {0,0,1,1,1}; int *p1 = t1, *p2 = t2; while (!*p1++ || !*p2++); cout << (p1-t1) << endl; cout << (p2-t2) << endl; } 

我的意思是,2个inttypes的数组被创build和填充值,2个指针被创build并指向每个数组,然后我开始有麻烦了。

 while (!*p1++ || !*p2++); 

对我来说这是说0移动*p1的位置一个位置或者0移动*p2的位置一个位置,我对这个假设真的没有信心吗?

 cout << (p1-t1) << endl; 

所以然后我们转到cout ,现在我的意思是,我从t1的位置减去p1的位置,其中p1被while定位, t1指向数组中的第一个位置。 再次我可能是完全错误的我只是学习指针,所以请记住,如果我错了我的假设。

while循环实际上很可怕。 在现实生活中,我从来没有见过这样的代码,并且会宣布任何程序员在现实生活中都这么做。 我们需要经过这一步一步:

 while (condition); 

我们在这里有一个空的陈述(“;”本身是一个空的陈述)。 条件被评估,如果它是真的,那么语句被执行(它什么都不做,因为它是一个空的语句),我们又重新开始。 换句话说,条件反复评估,直到它是假的。

 condition1 || condition2 

这是一个“或”声明。 第一个条件被评估。 如果这是真的,那么第二个条件不被评估,结果是“真”。 如果它是假的,则评估第二个条件,结果是“真”或“假”。

 while (condition1 || condition2); 

这是评估第一个条件。 如果这是真的,我们从头开始。 如果它是假的,我们评估第二个条件。 如果那是真的,我们从头开始。 如果两者都是假的,我们退出循环。 请注意,第二个条件仅在第一个条件为假时才被评估。 现在我们来看看条件:

 !*p1++ !*p2++ 

这与*(p1 ++)== 0和*(p2 ++)== 0是一样的。无论结果如何,每个条件在被评估之后都会增加p1或p2。 如果* p1或* p2为零,则每个条件为真,否则为false。 现在我们检查每次迭代会发生什么:

 p1 = &t1 [0], p2 = &t2 [0] *p1++ == 0 is true, *p2++ == 0 is never evaluated, p1 = &t1 [1], p2 = &t2 [0]. *p1++ == 0 is true, *p2++ == 0 is never evaluated, p1 = &t1 [2], p2 = &t2 [0]. *p1++ == 0 is false, *p2++ == 0 is true, p1 = &t1 [3], p2 = &t2 [1]. *p1++ == 0 is false, *p2++ == 0 is true, p1 = &t1 [4], p2 = &t2 [2]. *p1++ == 0 is false, *p2++ == 0 is false, p1 = &t1 [5], p2 = &t2 [3]. 

t1与&t1 [0]相同。 p1-t1 ==&t1 [5] – &t1 [0] == 5. t2与&t2 [0]相同。 p2-t2 ==&t2 [3] – &t2 [0] == 3。

你对t1t2p1p2评估是正确的。

 while (!*p1++ || !*p2++); 

我不喜欢这种编码风格,因为很容易假设程序员错误地在那里放置了分号。 为了表明一个空的身体是真正意图的,空的身体应该以某种方式加以区分(如同一个评论,放在一个单独的行,或使用大括号代替)。

只要条件true while进入人体。 由于这是一个逻辑或expression式,所以!*p1++!*p2++while循环终止前必须为false 。 当*p1++*p2++变为非零时,会发生这种情况。 由于逻辑或 短路 (如果第一个expression式是true ,则不计算第二个expression式),在每次迭代开始时, p1p2的进程就会出现以下情况:

 iter p1 *p1 p2 *p2 condition ---- -- --- -- --- --------- 0 &t1[0] 0 &t2[0] 0 !*p1++ is true, !*p2++ not evaluated 1 &t1[1] 0 &t2[0] 0 !*p1++ is true, !*p2++ not evaluated 2 &t1[2] 1 &t2[0] 0 !*p1++ is false, !*p2++ is true 3 &t1[3] 1 &t2[1] 0 !*p1++ is false, !*p2++ is true 4 &t1[4] 1 &t2[2] 1 !*p1++ is false, !*p2++ is false 

由于每次迭代使用后增量 ,因此p1以值&t1[5]结束,并且p2以值&t2[3]

相同arrays中的指针相减以数组元素的数量来衡量两个指针之间的距离。 在大多数expression式中使用的数组名将衰减到等于指向其第一个元素的值。 所以t1衰减到&t1[0]t2衰减到&t2[0]

从而:

 p1 - t1 => 5 p2 - t2 => 3 

这里要注意的关键是如何评估expression式(a || b) 。 首先,评估expression式a 。 如果a返回true,则不计算b因为具有True的任何事物的ORTrue 。 这被称为短路。

它有助于以下列方式增强代码 –

 int main(void){ int t1[] = {0,0,1,1,1}, t2[] = {0,0,1,1,1}; int *p1 = t1, *p2 = t2; cout << *p1 << " " << *p2 << endl; cout << p1 << " " << p2 << endl; while (!*p1++ || !*p2++) { cout << *p1 << " " << *p2 << endl; cout << p1 << " " << p2 << endl; } cout << (p1-t1) << endl; cout << (p2-t2) << endl; return 0; } 

输出:

 0 0 0x7fff550709d0 0x7fff550709f0 0 0 0x7fff550709d4 0x7fff550709f0 1 0 0x7fff550709d8 0x7fff550709f0 1 0 0x7fff550709dc 0x7fff550709f4 1 1 0x7fff550709e0 0x7fff550709f8 5 // Final p1 - t1 3 // Final p2 - t2 

!*p1++相当于(!(*(p1++)) 。这是后增值操作符。它增加指针但返回旧值(在增量之前)。

循环中的expression式被评估5次。

  1. 在第一次迭代中,p1递增。 由于*p1的当前值(递增之前)是0,所以! 0返回1 。 由于短路,其余的expression不被评估。 因此只有p1得到增加。

  2. 同样的事情发生在下一个循环。

现在,我们有p1 = t1 + 2 indicesp2 = t2

  1. 在第三次迭代中, *p1当前值不再是0 。 因此p1p2都是递增的。

  2. 同样的事情发生在第四次迭代。

请注意,在前四次迭代中, p1p2指向0 – 所以左侧或右侧的不是True ,因此while循环继续。

  1. 在第五次迭代中,p1和p2都是递增的,但是既然都不指向0值,循环就会退出。

因此, p1递增5次, p2递增3次。

总结p1 - t1将包含1 +在t1t2 (2 + 2 + 1)的开始连续出现的0的数目。 在t2 (2 + 1)的开始, p2 - t2将评估为1 +连续出现的0的数目。

第一:

 while (!*p1++ || !*p2++); 

这意味着当p1 的内容0 ,每次循环加1p1直到变为non-zero 。 此后,当p2的内容为0 ,每次循环将p1p2都加1 。 如果在任何时候p1 的内容再次变为0逻辑重复(我知道这是混乱)。

基本上在一段while(first || second)风格testing第二部分是testing,如果第一部分失败。 无论testing通过还是失败,指针都会增加。

你对(p1-t1)假设是正确的。 这个计算给你t1和p1之间的整数 (因为它们是int指针)。 因为t1是数组的开始,所以计算实际上给了你指向p1指向的数组的索引(偏移量)。

注1:如果p1t1char指针,那么减去它们会给你它们之间的字符数 。 如果它们是float指针,那么减去它们会得到浮点数等等。指针算术以它们指向的数据types为单位进行加减。

注2:严格地说t1是一个数组types。 当你在指针上下文中使用它时,它会折叠成一个指针。 例如在指针算术中,或者当你把它赋给一个指针variables。 如果让你感到困惑,不用担心,大多数情况下它只是作为指针工作,因为只要上下文隐含,编译器就会自动进行转换。

至于问题是什么,这将打印在控制台上,答案是0 0之前,你删除; while循环的结尾。

这个循环的意义是什么?

首先你使用的是OR,意思是如果p1或p2指向的任何一个值是0,块将被执行。 因此,直到p1指向第三个元素(p1-t1)将给你在t1中交叉元素的数量,而(p2-t2)将为0,因为(p1-t1)将返回true,所以第二个条件将不会被检查。 当p1指向1时,它会开始递增p2,直到它指向t2的第3个元素,结束。

这是我相信的所有这些任务。

这个关系可以帮助你更好地理解while循环中的条件:

 arr[ i ] == * ( arr + i ) 

当做指针减法(如果指针是相同types的),结果是两个元素之间的距离(在数组元素中)。

假设p1p2都是T*types的指针。 然后,计算的值是:

 ( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )