在关于C语言的经典书籍的第1.9章" C编程语言"布莱恩&丹尼斯,有一个关于功能' getline'的代码。用于将下一行输入文本复制到char类型字符串并检查溢出。我引用下面的代码:
int getline(char line[], int maxline);
int getline(char s[], int limit)
{
int c,i;
for (i=0; i<limit-1 && (c=getchar())!=EOF && c!='\n'; ++i) /* ** */
s[i]=c;
if (c == '\n') {
s[i]=c;
++i;
}
s[i] = '\0';
return i;
}
问题在于:参数&#39;限制&#39;是行的最大长度,因此数组s []只能包含从s [0]到s [limit-1]的元素集合。如果变量c到getchar()的最后一个字符是&#39; \ n&#39;并且这个字符的索引是limit-1,然后判断部分是&#39; for&#39;循环将失败,因为&#39; i == limit-1&#39;但不是&#39; c!=&#39; \ n&#39; (根据从左到右的顺序)。接下来,if子句将起作用,因为&#39; c ==&#39; \ n&#39;&#39;,然后s [limit-1] = c,那么++ i将设置i的值进入极限。 S [I] =&#39; \ 0&#39;会溢出,因为s [limit]超出了字符串的限制。我的分析是否合适?感谢您提供任何有用的答案。
答案 0 :(得分:4)
你的分析是错误的。如果i == limit-1
,由于短路评估,循环会在不读入c
的情况下中断。所以,你永远不要输入if (c == '\n')
。 i
仍然是limit-1
,并且没有溢出。
从概念上讲,你可以想到这样的循环条件:“如果i
低于limit-1
,则读取一个字符,如果它不是EOF或换行符,则输入循环体。”因此,如果i
为limit-1
,则您永远不会阅读。
答案 1 :(得分:3)
此代码中有两个短路的评估点。见下文
for (i=0; i<limit-1 && (c=getchar())!=EOF && c!='\n'; ++i)
// ( A ) ( B ) ( C )
全部用&&
链分开。执行此代码时,所有三个必须为true或循环将中断。但是在短路评估中会发生以下情况:
...因此
i<limit-1
为false,既不 getchar()
,也不会与EOF进行比较,也不会与'\n'
进行比较。(c=getchar())!=EOF
为false,则不执行与'\n'
的比较。'\n'
的比较。我希望这是有道理的。