为什么在C中使用指针时不需要指定数组大小?

时间:2017-09-12 09:38:32

标签: c arrays string pointers memory-management

为什么在使用指针时不需要指定数组大小?

我是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);


}

2 个答案:

答案 0 :(得分:7)

似乎工作正常,实际上,它是undefined behavior

对于任何未初始化的自动存储类型的局部变量,如果未明确初始化,则内容是不确定的。您的代码中的greet也是如此。

所以,基本上,你试图写入一个有效性未知的记忆。最好由greet指向的内存位置无效。您必须确保用作目标缓冲区的指针指向某个有效的内存位置。您可以通过以下方式之一完成此操作

  1. 使指针指向有效的内存位置

    char *greet = NULL;
    char buf[BUFSIZ] = {0};
    greet = buf;
    
    .
    .
    .
    
    fgets(greet, BUFSIZ, stdin);
    
  2. 使用动态内存分配器分配内存(在运行时),如

    char * greet = malloc(BUFSIZ);
    
    if (greet) {// allocation successful....}
    

    在这种情况下,您还需要处理清理工作。

  3. 那就是 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);