首先将字符串指针分配给已分配的内存并直接分配给字符串文字有什么区别?

所以我的理解是这两个代码块是有效的并且做同样的事情。

1.)

char *ptr = malloc(5); ptr = "hi"; 

2.)

 char *ptr = "hi"; 

我想知道两者之间的差异,比如一个优于另一个。

前者是一个错误,代码应该永远不会写。

它使用字符串文字的地址覆盖malloc()返回的指针,删除原始指针并泄漏内存。

必须使用strcpy()或其他一些内存复制方法来使用字符串初始化新分配的堆内存。

第二个只是将字符串文字的(运行时常量)地址分配给指针ptr ,不会在任何地方复制字符。

第一位是可能的内存泄漏,第二位依赖于正在使用的隐式const存储类,并将不可变字符串的内存地址分配给指针。
基本上:

 char *ptr = malloc(5);//allocates 5 * sizeof *ptr //then assigns the address where this block starts to ptr //this: ptr = "hi";//assigns position of 'h','i', '\0' in read-only mem to ptr 

现在,您分配的地址( ptr指向的地址)仍然被分配。 区别在于你不再“处理”它,因为ptr的值已经改变了。 没有指针指向你使用malloc分配的动态内存,所以管理内存变得相当棘手……你可能无法free它,现在在ptr上调用free会导致未定义的行为。
如果你写:

 char *ptr = "hi"; 

那你实际上在写:

 const char *ptr = "hi"; 

这意味着您无法更改ptr指向的字符串:

 ptr[0] = 'H';//IMBOSSIBRU 

替代方案是:

 char string[] = "Hi";//copies Hi\0 to string //or char *ptr = malloc(5); strcpy(ptr, "hi");//requires string.h 

上面两个片段之间的区别在于第一个创建了一个堆栈数组,第二个在堆上分配了一块内存。 堆栈内存更容易管理,更快,几乎在所有方面都更好,除了它不那么丰富,并且不能真正用作返回值…

每个进程都有一个字符串文字池。 无论何时在代码中创建字符串文字,文字都会保存在池中,并返回字符串的地址(即指向池中某处的地址)。 因此,您在第一个选项中创建了内存泄漏,因为您正在覆盖使用malloc收到的地址。

在第一种情况下

 char *ptr = malloc(5); ptr = "hi"; 

存在内存泄漏,之后您将ptr指向字符串文字“hi”,它确实需要堆中的任何内存(这就是存在内存泄漏的原因)。

但是,如果你正在分配内存,如果你正在使用

 strcpy (ptr, "hi"); 

那么如果你愿意你可以修改它

 strcpy (ptr, "hello") 

有一个条件,你之前分配了足够的内存。

但在你的情况下,你正在指定一个带有字符串文字的指针ptr ,在这里你将无法修改它

 ptr = "hello" // not valid. This will give a segmentation fault error 

在第二种情况下,没有内存泄漏,并且您正在指向指向字符串文字的指针,因此它的值无法修改,因为它将存储在只读数据段中。