提问人:Helix Development 提问时间:11/6/2023 更新时间:11/6/2023 访问量:76
C fgets 字符串长度不限于输入
C fgets string length not limited to input
问:
我很困惑,即使我提供的 char 数组最多只能有 5 个字符长,但如果提供更大的限制,长度也可以超过 5 个字符。mystring
fgets
#include <stdio.h>
#include <string.h>
int main() {
char mystring[5];
fgets(mystring, 10, stdin);
printf("len: %d", strlen(mystring));
}
如果我输入 8 个或更多字符并按 Enter,则长度为 9。考虑到数组的长度设置为 5,这是怎么发生的?mystring
mystring
答:
1赞
Chris
11/6/2023
#1
当您只有 5 个有效字节要读入时,您可以告诉读取 10 个字节。但是,您处于未定义行为的领域,程序可能会按预期“工作”,或者可能发生其他任何事情。fgets
如果您的程序即使在使用这种未定义的行为时也能正常工作,那么您的程序保留的空间可能比 5 个字节多得多,因此写入数组末尾实际上不会导致运行时错误。不要指望这个。
例如,您的代码在我的计算机上编译时,无法逃脱这种命运。
$ cat test.c
#include <stdio.h>
#include <string.h>
int main() {
char mystring[5];
fgets(mystring, 10, stdin);
printf("len: %d", strlen(mystring));
}
$ gcc test.c
test.c: In function ‘main’:
test.c:9:19: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t {aka long unsigned int}’ [-Wformat=]
printf("len: %d", strlen(mystring));
~^ ~~~~~~~~~~~~~~~~
%ld
$ ./a.out
hello world foo bar
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
注意:可以通过对 类型为 的参数使用格式说明符来消除警告。%zu
size_t
评论
2赞
Jonathan Leffler
11/6/2023
哪个版本的 GCC 推荐而不是格式(或)?这是一个奇怪的选择,因为它需要一个有符号的长整型,而消息说等同于 .%ld
%lu
%zu
size_t
unsigned long
3赞
Harith
11/6/2023
#2
考虑到数组 mystring 的长度设置为 5?
一旦抽象状态机达到未定义的行为,就无法对执行的继续做出进一步的假设。
请参阅:未定义、未指定和实现定义的行为。
考虑:
// fgets(mystring, 10, stdin);
fgets(mystring, sizeof mystring, stdin);
旁白:
strlen()
返回 a ,而不是 .调用未定义的行为作为格式说明符与相应的参数不匹配。size_t
int
printf()
// printf("len: %d", strlen(mystring));
printf("len: %zu", strlen(mystring));
评论
0赞
Chris
11/6/2023
OP 似乎非常清楚,他们不应该提供比缓冲区更大的尺寸,而是询问它为什么“有效”。据推测,提供这种投入是一项学术实验。
0赞
Harith
11/6/2023
@Chris承认。
评论
sizeof (mystring)