我知道此问题之前已被多次询问过,但我对下面的代码提出了一些问题。
所以下面的代码不起作用,因为在我的while循环中我有str != end
而不是str < end
。为什么必须str < end
?我很困惑,因为似乎条件str != end
应该以相同的方式工作,因为指针最终将指向相同的位置。
我的第二个问题是为什么我们必须while(*end){end++;}
代替while(end){end++}
。无论如何,当我们越过终点时,指针是否无效? while(end){end++}
如果不正确,该怎么办?
我的最后一个问题是,在此代码的其他变体中,我已经看到在此函数顶部添加了一个条件if(!(*str)){return;}
。这有必要吗?没有这个,我的代码似乎处理空字符串。此外,与*end
vs end
类似,为什么我们必须!(*str)
代替!(str)
?
void reverse(char *str){
char *end = str;
while(*end){
end++;
}
end--;
while(str != end){
char tmp = *str;
*str = *end;
*end = tmp;
str++; end--;
}
}
答案 0 :(得分:2)
您同时递增str
和递减end
(str++; end--;
)。因此,当你来比较它们时,它们可能会互相跳过,永远不会平等。
在当前的实现中,如果传递了一个空字符串(*str==0
),那么仍无条件地递减end
(end--
,第5行函数) 。所以现在看起来str
开始大于end
这是坏消息如果str!=end
是你的循环中的条件(我说&#34;看起来喜欢&#34;因为,作为pointed out by Cornstalks,它实际上是未定义的行为 - 在某些情况下,编译器可能会调整end
以使得点太远 str
)。无论如何,一旦你取消引用end
,它就会出现更糟糕的消息,因为你很可能会搞乱未分配的内存。
至于你关于!(*str)
的问题:if *str==0
表示字符串为空,而str==0
表示调用函数已经传递了一个NULL字符串指针。你应该检查两种可能性 - 具体来说,为了避免炸毁宇宙,首先检查指针是否为NULL,之前你试图取消引用它。
答案 1 :(得分:1)
Why does it have to be str < end?
考虑具有偶数个字符的字符串会发生什么,例如“ABCDEF”。
why we have to do while(*end){end++;} instead of while(end){end++}.
您正在寻找终止字符串的空字节,即当指针end
指向空字节时。使用后一版本,只有当指针指向地址零时才使循环终止。
I've seen a condition added to the top of this function that says if(!(*str)){return;}. Is this necessary?
否 是的!正确指出其他答案时,检查可以避免执行--end;
。
答案 2 :(得分:1)
您需要str < end
,因为您str++; end--;
。如果结束正好在str之上并且您str++; end--;
,会发生什么?在那之后,str将正好在结束之后,它们会有所不同,但你不想继续你的循环。
结束总是一个指针。它可能指向一些有效的内存,或者它可能指向某个地方,如果您尝试访问该内存,它会给您一个段错误。增加指针只会使其指向更高的地址。它不会因为地址无效而变为NULL。这就是为什么你必须查看*end
以找到空终止字符串的结尾。
使用当前代码,似乎没有必要检查if(!(*str)){return;}
,因为str和end变为相同的事实会捕获空字符串。但是,如果有人使用NULL指针调用您的函数,则添加if(!str){return;}
以避免出现段错误可能是个好主意。
答案 3 :(得分:1)
只有当您的字符串具有奇数个字符时,条件str != end
才能为您提供足够的结果。否则你很可能有以下顺序:
str 0 1 2
end 3 2 1
此时,str != end
仍然是正确的,尽管你的指针已经通过了字符串的中间。
while(end)
不检查指针是否有效,因为它指向您先前分配给该内存地址的值。它仅检查end
是否与NULL
不同。
这在技术上并不是必需的,但它确保在字符串为空时立即退出函数,而不进行任何额外的工作。
修改:作为Cornstalks的pointed out, 需要检查此内容。
答案 4 :(得分:1)
我想具体回答有关if(!(*str)){return;}
是否必要的问题。
是的,您当前的代码是绝对必要的。
没有它,end--
将被执行。这意味着end
将在有效范围[str, str + strlen(str) + 1]
之外递减(您可以将指针递增到其内存块的末尾一个,但是您无法取消引用它)。
<强> Doing so is actually undefined behavior 即可。如果有效的内存范围是未定义的行为,则指向外部,即使您没有取消引用它。
例如,如果您的计算机使用segmented memory model,则您的比较(str < end)
可能仍然为真,即使您有一个空字符串并且您递减了end
(在这种情况下) ,end
可以缠绕,str < end
仍然是真的。)
例如,考虑一个aaaa:bbbb
分段内存模型。 aaaa
是细分,bbbb
是细分中的偏移量。如果str
是指向1234:0000
的指针,并且您递减它,则它可能是新值1234:ffff
。为什么段没有减少?因为编译器知道你不能跳段;指针只能指向当前段内的数据。因此,在进行指针运算时,它只会修改指针的偏移量(低两个字节)。现在,str < end
仍然是真的,代码将继续并破坏。
答案 5 :(得分:0)
似乎条件
str != end
应该以相同的方式工作,因为指针最终将指向相同的位置。
这取决于字符串是偶数还是奇数字符。在前一种情况下,str
和end
指针会相互移动过去,永远不会相等。
如果不正确,
while(end){end++}
正在做什么?
这是检查end
是否为NULL
,而您未将end
设为NULL
。