在K&R的"C编程语言"(第二版(的第29页,我读到了一个我认为被破坏的过程。因为我是初学者,我希望我错了,尽管我无法解释为什么。
代码如下:
#include <stdio.h>
#define MAXLINE 1000 // Maximum input line size
int get1line(char line[], int maxline);
void copy(char to[], char from[]);
// Print longest input line
int
main()
{
int len; // Current line lenght
int max; // Maximum lenght seen so far
char line[MAXLINE]; // Current input line
char longest[MAXLINE]; // Longest line saved here
max = 0;
while ((len = get1line(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) // There was a line to read
printf("Longest string read is: %s", longest);
return 0;
}
// `get1line()` : save a line from stdin into `s`, return `lenght`
int
get1line(char s[], int lim)
{
int c, i;
for (i = 0; i < lim -1 && (c = getchar()) != EOF && c != 'n'; ++i)
s[i] = c;
if (c == 'n') {
s[i] = c;
++i;
}
s[i] = ' ';
return i;
}
// `copy()` : copy `from` into `to`; assuming
// `to` is big enough.
void
copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != ' ')
++i;
}
我的困惑是:我们正在使用函数get1line
,并假设在for
循环结束时i
设置为 lim -1
。然后下面的 if
-语句将在 lim
更新i
,导致下一条指令(将NULL
字符放在字符串末尾的指令(损坏堆栈(因为在这种情况下没有分配s[lim]
(。
代码坏了吗?
总结:不可能同时使用 i == lim-1
和 c == 'n'
退出循环,因此您担心的情况永远不会出现。
详细:我们可以重写 for 循环(同时保留其含义(以使事件的顺序清晰。
i = 0;
for (;;) {
if (i >= lim-1) break; /* (1) */
c = getchar();
if (c == EOF) break; /* (2) */
if (c == 'n') break; /* (3) */
s[i] = c;
++i;
}
在循环出口 (1( 处,不可能是这样c == 'n'
因为如果是这种情况,那么循环将在上一次在 (3( 处退出。
在循环出口 (2( 和 (3( 处,不可能是i == lim-1
的情况,因为如果是这种情况,那么循环将在 (1( 处退出。
* 这取决于lim
至少为 2,因此实际上有以前的循环时间。该程序只调用lim
等于 MAXLINE
的 get1line
,所以情况总是如此。
** 您可以通过在循环开始之前将c
初始化为 'n'
以外的值,使函数在小于 2 时lim
安全。但是如果你担心这种可能性,那么你可能还需要关注lim
INT_MIN
的可能性,这样lim-1
由于整数溢出而导致未定义的行为。
如果lim == 0
代码是错误的,因为它使用未初始化c
并添加了\0。如果lim == 1
也是错误的,因为它使用未初始化c
。使用 lim < 2
调用函数不是很有用,但它不应该像这样失败。
如果lim > 1
则函数正常
for (i = 0; i < lim -1 && (c = getchar()) != EOF && c != 'n'; ++i)
s[i] = c;
如果i == lim-1
,或者如果c == EOF
或c == 'n'
,循环将退出。
如果第一个条件为真(
i == lim-1
(,则最后一个条件肯定不为真(除非lim < 2
,如上所述(。如果第一个条件为假(
i < lim-1
(,那么即使循环以c == n
退出,我们也知道缓冲区中有空间,因为我们知道i < lim-1
。