在 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] = '\0';
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]) != '\0')
++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,因此实际上循环中存在先前的时间。该程序仅调用 get1line
且 lim
等于 MAXLINE
,因此情况总是如此。**
** 当 lim
小于 2 时,您可以通过将 c
初始化为 '\n'
以外的值来使函数安全> 循环开始之前。但如果您担心这种可能性,那么您可能还需要担心 lim
为 INT_MIN
的可能性,因此 lim-1
由于整数溢出导致未定义的行为。
关于c - K&R 上的代码损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19084203/