为什么在使用指针时不需要指定数组大小?
我是C的新手,并试图更好地了解它是如何运作的。
如果我使用指针声明数组问候,我不需要指定数组大小。 如果我拿走指针,那么我需要定义数组的大小。
为什么编译器在使用指针声明char变量时不需要知道要分配的数组的大小,但是当我只声明一个char变量时它就会这样做。对于为什么会发生这种情况感到困惑。
这是我的示例代码:
int main()
{
char *greet; // Works fine.
// char greet; // Doesn't work. Crashes when entering text.
// char greet[]; // Doesn't work. Array size missing, won't compile.
// char greet[20]; // Works fine.
printf("Enter name\n>");
gets(greet);
printf("Hello %s", greet);
}
答案 0 :(得分:7)
似乎工作正常,实际上,它是undefined behavior。
对于任何未初始化的自动存储类型的局部变量,如果未明确初始化,则内容是不确定的。您的代码中的greet
也是如此。
所以,基本上,你试图写入一个有效性未知的记忆。最好由greet
指向的内存位置无效。您必须确保用作目标缓冲区的指针指向某个有效的内存位置。您可以通过以下方式之一完成此操作
使指针指向有效的内存位置
char *greet = NULL;
char buf[BUFSIZ] = {0};
greet = buf;
.
.
.
fgets(greet, BUFSIZ, stdin);
使用动态内存分配器分配内存(在运行时),如
char * greet = malloc(BUFSIZ);
if (greet) {// allocation successful....}
在这种情况下,您还需要处理清理工作。
那就是 DO NOT use gets()
, it is dangerous (and removed from latest standard, AFAIR). Use fgets()
instead.
作为一方而非,对于您提到的其他选项,
char greet;
也无效,fgets()
(是,甚至是gets()
)期望指向char
的指针,而非{{ {1}}。启用警告,您的编译器将尖叫。你最好停在那里!!
char type
语法无效,altotger,无需讨论。
char greet[];
这是正确的,只要您在char greet[20];
中传递小于/等于数组大小的大小即可。这没关系因为,
fgets()
是一个自动本地变量,因此存储将自动分配并且你将在界限范围内获得有效的记忆。一切都好。
答案 1 :(得分:6)
指针不是数组。你已经声明了一个指针,但你没有为指针所指的位置分配空间(我们通过malloc()
动态分配内存),因此当你尝试写入greet
时,你会调用 Undefined行为,这就是为什么它现在可能在你的机器上正常工作,但它不是!
另一方面,char greet[20];
会起作用,因为它是一个大小为20的数组,准备保存一个字符串。
此外,请考虑使用fgets()
而不是gets()
。 Difference between fgets and gets
把所有东西放在一起,我们可以得到:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *greet = malloc(21); // can hold a string of 20 characters, plus NULL terminator
// TODO: Check for malloc failure
printf("Enter name>\n");
fgets(greet, 21, stdin);
printf("Hello %s", greet);
// Never forget to deallocate your dynamic memory!
free(greet);
return 0;
}
通过使用固定大小的数组,代码看起来像这样:
char greet[21];
printf("Enter name>\n");
fgets(greet, 21, stdin);
printf("Hello %s", greet);