#include <stdio.h>
int main() {
char *t = "hello world";
puts(t);
//printf("%s", t);
t = "goodbye world";
puts(t);
}
t的内存未分配,所以为什么我在运行时没有出现段错误?指向C风格字符串的指针未分配
#include <stdio.h>
int main() {
char *t = "hello world";
puts(t);
//printf("%s", t);
t = "goodbye world";
puts(t);
}
t的内存未分配,所以为什么我在运行时没有出现段错误?指向C风格字符串的指针未分配
内存是分配给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机器上,你在地址零处得到一个零字节而不是崩溃,这导致了(部分)Henry Spencer'sTen Commandments“全世界都不是VAX” - 还有,“你不应该遵循空指针,混乱和疯狂等待你的结尾。“)
所以,在你的程序中,内存分配给t
和t
被初始化并分配给指向(只读)字符串常量,所以没有理由的程序崩溃。
t是一个指针,所以你只是让t指向另一个字符串。
由于字符串文字是静态分配在您的程序存储器中的 - 您不需要明确地为它们分配内存。
编译器需要为t
分配的所有内存在32位系统上是4个字节。记住它只是一个指针。在前几行中,它指向“hello world”,但在此之后,您将其更改为指向“再见世界”。 C将为您定义的字符串分配足够的内存,并将指针传递给您,以便您可以指向它们。你不必担心这一点。另请记住,这些字符串是静态和只读的,这意味着您不能安全地说t[4] = 'b';
。
你能说说为什么你会期望它出现段错误? –