C Char指针

让我们说我们有一系列指针:

char *ptr[30];

现在这个工作正常,似乎没有做任何意想不到的事情! 我可以轻松输入名字。

 scanf("%s", ptr[1]); scanf("%s", ptr[2]); scanf("%s", ptr[3]); printf("%s\n", ptr[1]); printf("%s\n", ptr[2]); printf("%s\n", ptr[3]); 

我的问题是,如果一个指针可以用这种方式来存储名称的结尾数,那么为什么要使用malloc呢? 在这种情况下,ptr [1]不指向输入中的字符,而是指向新输入本身。 例如,如果ptr有mukul,ptr [1]应该指向’u’,如果在指定这样的指针时没有分配空间,那么限制是多少?

指针不能以这种方式使用。 它有时可能通过纯粹的机会为你“工作”,但是使用指针而不为它分配内存会导致未定义的行为 – 这意味着你的程序可能表现不正常并给你意想不到的结果。

请记住,仅仅因为您的程序编译和运行并不意味着它是正确的。 在C语言中,存在一类称为“未定义行为”的错误,其中许多错误使编译器很乐意让您无需抱怨。 这些包括覆盖缓冲区,使用未初始化的变量,或者取消引用不指向合法分配的内存块的指针。 显示未定义行为的程序有时甚至可能正常工作 – 但它们通常非常不稳定并且容易崩溃。

如果你使用你的例子中的内容,你只需要在你的ptr数组之后写下其他位置。 大多数编译器实际上应该至少给出一个警告。 您的程序会在大多数系统上崩溃,您只是非常幸运。

定义指针时:

 char *ptr = 0; // NULL pointer: dereferencing it will crash puts(ptr); // crash 

您只需创建一个指向内存中某个位置的链接:

 ptr = "string"; // dereferencing it will show the string puts(ptr); // displaying "string" 

因此,拥有一个指针数组只会创建一个对其他变量的引用列表。

要引用内存中的某个位置,必须为指针分配变量,或为每个指针分配内存。

你已经为30个指针分配了空间,但你没有将它们初始化为指向任何有意义的地方。 除非您在函数外部声明了数组,否则数组中的每个元素都将包含一些随机位字符串,该字符串可能与可写内存位置相对应,也可能不相对应。 如果我们绘制一张图片,它看起来就像这样(所有地址都是凭空而来的;不要认为这对应于任何真实的架构):

项目地址0x00 0x01 0x02 0x03
 ---- ------- ---- ---- ---- ----
 ptr 0xbbc81230 0x ??  0X?  0X?  0X?
            0xbbc81234 0x ??  0X?  0X?  0X?
            0xbbc81238 0x ??  0X?  0X?  0X?
            ...
            0xbbc812a8 0x ??  0X?  0X?  0X?           

其中0x?? 表示随机字节值。 对于你所描述的行为,每个随机值恰好指向可写内存,并且写入存储在那里的任何内容恰好没有任何直接的不良影响。

坏juju: 看起来你的代码工作正常,但实际上它的表现非常糟糕,并且可能导致程序中其他地方出现一些令人讨厌的运行时问题,这是一个很难调试的问题。

在尝试写入之前,您需要显式设置ptr数组的每个元素以指向有效的内存位置。

假设我们添加以下代码:

 ptr[0] = malloc(strlen("foo") + 1); strcpy(ptr[0], "foo"); ptr[1] = malloc(strlen("bar") + 1); strcpy(ptr[1], "bar"); 

我们动态分配了一些额外的内存来保存几个字符串,并将指针存储到ptr[0]ptr[1]那些新缓冲区。

我们的图片现在看起来像这样:

项目地址0x00 0x01 0x02 0x03
 ---- ------- ---- ---- ---- ----
            0x80ff0000'f''o''o'0x00
            ...
            0x80ffcdc0'b''a''r'0x00
            ...
 ptr 0xbbc81230 0x80 0xff 0x00 0x00
            0xbbc81234 0x80 0xff 0xcd 0xc0
            0xbbc81238 0x ??  0X?  0X?  0X?
            ...
            0xbbc812a8 0x ??  0X?  0X?  0X?           

ptr[0]现在包含一个缓冲区的地址,其大小可容纳4个char值,我们将字符串“foo”复制到该缓冲区。 类似地, ptr[1]包含另一个4字节缓冲区的地址,该缓冲区现在包含字符串“bar”。