带分号与不带分号的while循环内的指针递减[关闭]
Posted
技术标签:
【中文标题】带分号与不带分号的while循环内的指针递减[关闭]【英文标题】:pointer decrement inside while loop with semicolon vs without semicolon [closed] 【发布时间】:2019-12-04 17:10:52 【问题描述】:void* My_memmove(void *dest, const void *src, size_t size)
char *p1 = (char *)dest;
char *p2 = (char *)src;
if(NULL == p1 || NULL == p2)
return NULL;
p2 += size;
while(p2 != src && --p2 != dest)
if(p2 != src)
printf("inside IF \n");
p1 += size;
p2 = (char *)src + size;
while(size--)
*(--p1) = *(--p2);
else
printf("inside ELSE \n");
while(size--)
*(p1++) = *(p2++);
return dest;
int main(void)
char dest[15];
memset(dest, 0, 15);
printf("Enter the string : ");
scanf("%s", dest);
My_memmove(dest+3, dest, strlen(dest));
printf("dest+3 : %s \n", dest+3);
return (0);
您能否解释一下当 while(p2 != src && --p2 != dest) 后面没有分号时会发生什么? 因为上述程序适用于所有输入,除了大小为 4 的输入
结果:
输入字符串:12
在 IF 内
dest+3 : 12
输入字符串:123
在 IF 内
dest+3 : 123
输入字符串:1234
dest+3 : 4
输入字符串:12345
在 IF 内
dest+3 : 12345
输入字符串:123456
在 IF 内
dest+3 : 123456
大小为7时p2+size后的内存布局
p2+--+
|
src+-+ dst++ |
| | |
v v v
++-----+-------+--------+
|0|1|2|3|4|5|6|7|8| ... |
+-----------------------+
dest[15] -> |a|b|c|d|e|f|g|0|0| ... |
+-----------------------+
【问题讨论】:
while(predicate) body
,首先没有给出正文。第二,正文是;
。
这是一个苹果和橘子的比较。语句 2 是无用的,什么也不做。声明 1 不完整,因此我们无法说出它的作用。
@SRIKANTH 提供一个最小的完整程序来展示差异。
str
似乎没有在任何地方定义。
更新了可运行的代码和结果
【参考方案1】:
使用while
(或for
或if
),您有两种选择body。您可以将花括号用于多语句体:
while(condition)
multi;
statement;
body;
或者你可以去掉花括号,下一条语句将被视为循环体。这对于短正文的良好格式可能会很好:
if(condition)
return thing;
但它也可能与错误的格式混淆:
if(condition)
thing += thing2;
return thing;
只有第一个语句 (thing += thing2
) 实际上在 if
的正文中。不管怎样,return
每次都会运行。
分号本身就是空语句。它本身就是一个完整的声明,但它什么也没做。所以
while(condition);
是一样的
while(condition)
;
您的另一个不带分号的示例将提取代码中的下一条语句并将其用作循环体。
为了响应您的更新,让我们通过运行输入“abcd”的函数来查看您的字符串的内存:
src--+ dst-+
| |
v v
++-----+----------------+
|0|1|2|3|4|5|6|7|8| ... |
+-----------------------+
dest[15] -> |a|b|c|d|0|0|0|0|0| ... |
+-----------------------+
注意size
这里是4,所以当你做char *p2 = (char *)src;
和p2 += size;
时,你的指针看起来像:
p2+--+
|
src+-+ dst++|
| ||
v vv
++-----+----------------+
|0|1|2|3|4|5|6|7|8| ... |
+-----------------------+
|a|b|c|d|0|0|0|0|0| ... |
+-----------------------+
然后你做:
while(p2 != src && --p2 != dst)
你猜怎么着,--p2
正是dst
!所以你的循环没有运行就结束了,你只返回dst
,它是指向字符串中最后一个字符的指针。
这是尝试在其内部复制字符串的众多问题之一。您的来源和目的地重叠!
【讨论】:
谢谢!。我明白了。但是,根据 while 循环的行为,如果长度为 x (x > 3),则 if-else 块应执行 (x-3) 次。但是无论长度是多少,if-else 块只执行一次。你能解释一下吗? @SRI 请重新阅读我回答的后半部分。您的 while 循环条件取决于--p2 != dst
,但第一次运行条件时,它是错误的。所以你的 if-else 永远不会运行一次(永远不会进入循环)。
谢谢,但是,只有大小为4时才会发生,如果大小大于4,假设大小为7 然后条件在 3 次迭代中为真,然后在第四次迭代时条件变为假。因此 if-else 块应该执行 3 次。但这并没有发生。在问题中,我在大小为 7 时添加了内存布局。
@SRI "假设大小为 7,那么条件在 3 次迭代中成立" 不。条件,p2 != src && --p2 != dest
在您进入循环的第一次 时为真,但随后您运行while(size--) *(--p1) = *(--p2);
,这会减少p2
、size
次。我要在这里对你说实话,这段代码是一团糟。出于某种原因,您有一个嵌套循环,并且顶部有一个奇怪的循环。我强烈建议从这里开始。或者,如果这是一个课堂项目,请向您的教授寻求帮助。
非常感谢!,我终于明白了我造成的整个混乱。再次感谢您。【参考方案2】:
while(p2 != src && --p2 != dest)
没有终止分号,循环在每次迭代上执行下一条语句。使用分号,下一条语句只会在循环结束时执行一次。确切的区别将取决于该语句是什么。
int x = 5, int y = 0;
while (x--)
++y;
没有分号,++y
发生在每次迭代 (x = 5, 4, 3, 2, 1) 所以 y = 5。添加分号,它只发生在循环完成后,给 y = 1。
请注意,++y
是否在同一行,是否缩进,与 C 或 C++ 无关。
【讨论】:
我已经验证下一条语句只执行一次。 那么在你验证的情况下它只循环了一次。这就是语言的作用,更新后的示例代码中的if
和 else
适用于每个循环。查看这个可运行的示例rextester.com/EVS72895
我明白了,但我的代码中有些地方不正确。 if 或 else 块只执行一次。更新了可运行代码和结果。我一无所知。以上是关于带分号与不带分号的while循环内的指针递减[关闭]的主要内容,如果未能解决你的问题,请参考以下文章