【问题标题】:Why the char has to be a pointer instead of a type of char?为什么char必须是指针而不是char类型?
【发布时间】:2016-11-08 03:12:19
【问题描述】:
#include <stdio.h>

typedef struct {
    char * name;
    int age;
} person;

int main() {
    person john;

    /* testing code */
    john.name = "John";
    john.age = 27;
    printf("%s is %d years old.", john.name, john.age);
}

这是一个运行良好的代码,我只是有一个小问题。 在结构部分,我删除name之前的*后,这段代码就不再起作用了,但是无论age的类型是int还是指针,它总是可以正常工作。那么谁能告诉我为什么name 必须是一个指针而不仅仅是一种字符?

【问题讨论】:

    标签: c string pointers char


    【解决方案1】:

    char 类型是字符的缩写,可以容纳一个字符。 C 没有 string 类型,而是 C 中的字符串是 char'\0' 结尾的数组 - 空字符(以空结尾的字符串)。

    因此,要使用字符串,您需要一个指向包含大量字符的内存的指针。那么为什么它适用于带有或不带有*int。好吧,我们可以将年龄设为int,也可以有一个指向存储年龄的内存的指针。要么运作良好。但是我们不能在一个字符中存储一个字符串。

    【讨论】:

      【解决方案2】:

      这与您在printf 函数中的格式说明符有关。 %s 尝试输出字符串(读取一部分内存),%d 将 get 中的所有内容解释为整数,因此即使是指针类型也可以,但是,您不应该这样做,这是未定义的行为。

      我建议你阅读一些关于 C 的好书来很好地掌握这些东西,一个很好的列表在这里The Definitive C Book Guide and List

      【讨论】:

        【解决方案3】:

        但是无论年龄的类型是int还是指针,它总是可以正常工作的。

        这是未定义的行为。

        详细地说,双引号分隔的字符串(如上所示)是一个字符串文字,当用作初始化器时,它基本上为您提供了一个指向文字开头的指针,从而它需要存储一个指针变量。所以,name 必须是一个指针。

        OTOH,初始化器27 是一个整数文字(整数常量),它需要存储到int 变量中,而不是int *。如果您使用 27 来初始化 int * 并使用它,它工作(相反,似乎工作)因为那样,它稍后会通过尝试使用无效的内存位置来调用 undefined behavior .

        FWIW,如果你尝试类似的东西

        typedef struct {
            char * name;
            int *age;
        } person;
        

        然后

        john.age = 27;  //incompatible assigment
        

        编译器会警告你从整数到指针的错误转换。

        【讨论】:

          【解决方案4】:

          char *namename 是指向类型char 的指针。现在,当您使它指向"John" 时,编译器将John\0 即5 个字符存储到某个内存中,并返回该内存的起始地址。因此,当您尝试使用 %s(字符串格式说明符)进行读取时,name 变量会返回您读取到 \0 之前的整个字符串。

          char name :这里的name 只是一个具有 1 字节内存的字符。因此,您只能存储一个字符。此外,当您尝试读取时,您应该始终只读取一个字符 (%c),因为尝试读取更多字符会将您带到未分配给您的内存区域,因此会调用 Undefined Behavior

          int age : age 被分配了 4 个字节,所以你可以将一个整数存储到这个内存并读取,printf("%d", age);

          int *age : age 是一个指向 int 类型的指针,它存储一些内存的地址。与字符串不同,您不使用地址读取整数(松散地说,只是为了避免复杂性)。你必须取消引用它。因此,首先,您需要分配一些内存,将任何整数存储到其中并将该内存的地址返回给age。或者,如果您不想分配内存,您可以使用编译器的帮助,将值分配给age,如下所示,*age = 27。在这种情况下,编译器会将27 存储到某个随机内存中,并将地址返回给age,可以使用*age 取消引用,例如printf("%d", *age);

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-10
            • 2011-08-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多