6
I.  char *str = "Stack";

II. char *str = (char*) malloc(6);
    strcpy(str, "Stack");

以上两种方法有什么区别?

它们是相同的还是在窗帘后面有什么不同?

4

3 回答 3

24

上面的代码会导致问题。

第一个实例称为静态字符串分配和定义。对于诸如 等的普通变量int和非字符串数据类型,这样的声明将在堆栈上分配数据。在通过字符串文字(即:)初始化字符串的情况下"stack",它被分配在内存的只读部分中。

不应修改字符串本身,因为它将存储在内存的只读部分中。指针本身可以更改为指向新位置。

IE:

char strGlobal[10] = "Global";

int main(void) {
  char* str = "Stack";
  char* st2 = "NewStack";
  str = str2;  // OK
  strcpy(str, str2); // Will crash
}

为了安全起见,您实际上应该分配为指向 const 数据的指针,即:

const char* str = "Stack"; // Same effect as char* str, but the compiler
                           // now provides additional warnings against doing something dangerous

第二种称为动态分配,它在堆上分配内存,而不是在堆栈上。可以毫不费力地修改字符串。在某些时候,您需要通过free()命令释放这个动态分配的内存。

还有第三种分配字符串的方法,即栈上的静态分配。这允许您修改保存字符串的数组的内容,并且它是静态分配的。

char str[] = "Stack";

总之:

Example:                       Allocation Type:     Read/Write:    Storage Location:
================================================================================
const char* str = "Stack";     Static               Read-only      Code segment
char* str = "Stack";           Static               Read-only      Code segment
char* str = malloc(...);       Dynamic              Read-write     Heap
char str[] = "Stack";          Static               Read-write     Stack
char strGlobal[10] = "Global"; Static               Read-write     Data Segment (R/W)

您还应该阅读现代操作系统中的应用程序如何对数据进行分段。这将真正增加您对如何构建代码的理解。

参考


  1. 数据段,2013-04-15 访问,<http://en.wikipedia.org/wiki/Data_segment>
  2. 代码段,2013-04-15 访问,<http://en.wikipedia.org/wiki/Code_segment>
于 2013-04-15T17:49:00.383 回答
2

在第一种情况下,您的指针指向const char*在进程内存的只读部分中分配的 a。
在第二种情况下,您正在动态分配内存并最终将字符串“Stack”复制到您分配的内存中。

您最终必须使用free.

于 2013-04-15T17:47:02.643 回答
0

忘记其他声称存储在堆栈中的任何答案,因为它们是不正确的。(哦,现在这些答案已被删除..)

case I:你有一个指针str,它指向一个只读内存区域(该.rodata部分),其内容是"Stack".

case II:你有一个指针str,它指向一个动态分配的区域(在堆中),它的内容是,它是可修改的,并且在使用它后"Stack"应该通过调用来释放。free(str)

于 2013-04-15T17:54:16.643 回答