2
#include <stdio.h>

int main() {
    char *t = "hello world";
   puts(t);
   //printf("%s", t);
   t = "goodbye world";
   puts(t);
}

t 的内存没有分配,那么为什么我在运行它时没有出现段错误?

4

5 回答 5

4

t 是一个指针,所以你只是让 t 指向另一个字符串。

于 2012-08-26T16:12:44.493 回答
4

因为字符串文字是在程序内存中静态分配的 - 您不需要显式地为它们分配内存。

于 2012-08-26T16:12:51.780 回答
2

内存分配给; t为其分配了足够的内存来保存指针(通常,在 32 位程序中为 4 个字节,在 64 位程序中为 8 个字节)。

此外,初始化t确保指针指向某处:

char *t = "hello world";

字符串文字也在某处分配了空间。通常,这是在内存的只读部分,所以你真的应该使用const char *t = "hello world";,即使你不使用显式const,你也不应该尝试修改t指向的字符串。但是编译器的问题是确保t指向有效的地方。

同样,赋值后:

t = "goodbye, Cruel World!";

该变量指向编译器分配的空间。只要您不滥用它(并且您的代码没有),这很好。

会让你陷入麻烦的是这样的事情:

char *t;
puts(t);   // t is uninitialized; undefined behaviour
t = 0;     // equivalently, t = NULL;
puts(t);   // t contains the null pointer; undefined behaviour

未初始化的局部变量可以包含任何值;你无法可靠地预测会发生什么。在某些机器上,它可能包含空指针并导致崩溃,但这不是您可以依赖的。

空指针不指向任何有效的东西,因此取消引用空指针会导致未定义的行为,而且这种未定义的行为通常会导致崩溃。(经典地,在 DEC VAX 机器上,您在地址零处得到一个零字节而不是崩溃。这(部分)导致亨利斯宾塞的 十诫之一“全世界都不是 VAX”——以及“你不应该跟随 NULL 指针,因为混乱和疯狂在它的尽头等待着你。”)

因此,在您的程序中,内存被分配tt初始化并分配为指向(只读)字符串常量,因此程序没有任何借口崩溃。

于 2012-08-26T16:40:11.683 回答
2

t这里是一个指向匿名字符串第一个字符的指针,它可以在只读内存中。一个好主意是将指针声明为指向的指针const char

const char *t = "hello world";

另请参见此处

于 2012-08-26T16:35:31.663 回答
2

编译器需要分配的所有内存t是 32 位系统上的 4 个字节。请记住,它只是一个指针。在前几行中,它指向“hello world”,但之后您将其更改为指向“goodbye world”。C 将为您定义的字符串分配足够的内存并将指针传递给您,以便您可以指向它们。你不必担心这一点。还要记住,这些字符串是静态的和只读的,这意味着你不能安全地说t[4] = 'b';.

于 2012-08-26T16:38:13.703 回答