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

Bri*_*446 0 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);


}
Run Code Online (Sandbox Code Playgroud)

Sou*_*osh 7

似乎工作正常,实际上,它是未定义的行为.

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

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

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

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

    char * greet = malloc(BUFSIZ);
    
    if (greet) {// allocation successful....}
    
    Run Code Online (Sandbox Code Playgroud)

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

也就是说,不要使用,它是危险的(并从最新标准,AFAIR中删除).改用. gets()fgets()


作为一方,没有,对于你提到的其他选项,

  • char greet;也是无效的,fgets()(是的,甚至gets())期望一个指针char,而不是一个char type.启用警告,您的编译器将尖叫.你最好停在那里!!

  • char greet[]; 语法无效,altotger,无需讨论.

  • char greet[20];这是正确的,只要你传递一个小于/等于数组大小的大小,就可以了fgets().这没关系因为,

    • 这里greet是一个自动局部变量,因此将自动分配存储空间
    • 数组名称作为函数参数传递,衰减到指向数组中第一个元素的指针

    并且你将在界限内获得有效的记忆.都好.

  • 哇...任何澄清以及downvotes? (2认同)

gsa*_*ras 6

指针不是数组.你已经声明了一个指针,但你没有为指针指向的位置分配空间(我们通过动态分配内存malloc()),因此当你尝试写入时greet,你调用Undefined Behavior,这就是为什么它似乎在你的机器上工作正常,现在,但事实并非如此!

另一方面,char greet[20];它将工作,因为它是一个大小为20的数组,准备保存一个字符串.

而且,考虑使用fgets()结束gets().fgets和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;
}
Run Code Online (Sandbox Code Playgroud)

通过使用固定大小的数组,代码看起来像这样:

char greet[21];
printf("Enter name>\n");
fgets(greet, 21, stdin);
printf("Hello %s", greet);
Run Code Online (Sandbox Code Playgroud)