在C中初始化一个char指针。为什么认为危险?

时间:2012-01-09 21:41:30

标签: c pointers initialization char

  

可能重复:
  What is the difference between char s[] and char *s in C?

我初始化一个char指针:

char *a="test";

我在某些地方读到这被认为是 只读 ,这很危险。

这是否意味着"test"没有在堆中分配空间?这是否意味着字符串“test”可以在以后的程序中写出来?

---扩展我的问题---

如果我已按上述方式初始化a,那么我会进行一系列其他初始化,例如:

int b=20;
char c[]="blahblahblah";

内存中的“测试”是否会被“20”或“blah”覆盖?或者这种情况没有根据?

7 个答案:

答案 0 :(得分:14)

这很危险,因为字符串不可修改。尝试这样做会导致 未定义的行为

所以最好这样做:

const char *a = "test";

你是正确的,在这种情况下"test"没有在堆或堆栈*上分配,而是位于不可修改的静态内存中。

*标准对堆栈或堆没有任何说明,尽管这通常是如何实现的。

另一方面:

char a[] = "test";

可以安全修改,因为它只是简短形式:

char a[] = {'t','e','s','t','\0'};

这是一个普通的可修改数组。

答案 1 :(得分:1)

C程序中的文字字符串被认为是只读的,编译器/链接器/加载程序可以将该字符串的内存安排在内存中,以防止写入。

根据您的编译器和操作系统,以下内容可能会触发运行时错误:

char *a = "test";
a[0] = 'T';

当然,如果您实际上并未尝试更改字符串数据,那么这样做本身并不是危险。但是,让编译器通过声明指针const来帮助您确保这一点很有用:

const char *a = "test";

使用此声明,尝试a[0] = 'T'将是编译错误,因此将比运行时更快地检测到。

答案 2 :(得分:1)

尝试修改字符串文字的内容将调用未定义的行为(意味着从段错误到代码按预期工作);最好总是假设字符串文字是不可写的。

因此,正如所写的那样,a不应该是任何试图修改它所指向的字符串的函数的目标。

**编辑**

C语言定义没有说明堆栈或堆;它指定了对象的生命周期和可见性,并且由实现将其映射到特定的体系结构和内存模型。必须分配字符串文字,以便它们在程序的生命周期内可用。几种常见的体系结构将它们放在只读数据段中;有些人把它们放在一个可写的数据段中。有些允许您在编译时选择哪个。

答案 3 :(得分:0)

所有字符串文字都是只读的,即使它们的类型可能不是这样。字符串文字的类型为char[],(例如,"Hello"的类型为char[6]'\0'字符的一个额外值。虽然它不是const - 合格,但标准在§6.4.5/ 6中说明如下:

  

...如果程序试图修改这样的数组,行为是   理解过程科幻奈德。

如果你想要一个可变版本,你必须复制一个字符串,或者像这样声明它:

char a[] = "test";

答案 4 :(得分:0)

Exactly.

  

例如,由C中的char s[] = "hello world"定义的字符串和“main”之外的int debug=1之类的C语句将存储在初始化的读写区域中。像const char* string = "hello world"这样的C语句使字符串文字“hello world”存储在初始化的只读区域中,字符指针变量字符串存储在初始化的读写区域中。例如:static int i = 10将存储在数据段中,global int i = 10将存储在数据段

答案 5 :(得分:0)

  

我在某些地方读到这被认为是只读的,这很危险。

字符串文字确实是只读的。

  

这是否意味着“测试”没有在堆中分配空间?

标准是否指定了是否分配了字符串的空间。它通常在程序的静态部分,但标准甚至没有提到堆。

  

这是否意味着字符串“test”可以在以后的程序中写出来?

写字符串是未定义的行为。

答案 6 :(得分:0)

"test"之类的字符串文字是只读的,因此无法修改它们。因此,任何修改它们的尝试都将导致未定义的行为。

例如:

char *a = "test";
*a = 'b';

*a = 'b';是未定义的行为。

因此,如果您想修改它们,则需要使用数组

char a[]="test";

因此,您可以通过执行以下操作将“测试”修改为“最佳”:

a[0] = 'b';