使用malloc在C中正确使用/创建动态cstring?

使用malloc在C中正确使用/创建动态cstring?,c,malloc,cstring,C,Malloc,Cstring,以下代码始终显示故障: char *test3 = (char *) malloc(sizeof(char) * 5); test3 = "asdf"; printf("%s\n", test3); 以下代码不存在故障: char *test3 = (char *) malloc(sizeof(char) * 5); test3[0] = 'a'; test3[1] = 'b'; test3[2] = 'c'; test3[3] = 'd'; test3[4

以下代码始终显示故障:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3 = "asdf";
  printf("%s\n", test3);
以下代码不存在故障:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3[0] = 'a';
  test3[1] = 'b';
  test3[2] = 'c';
  test3[3] = 'd';
  test3[4] = '\0';
  printf("%s\n", test3);
我想问题可能是如何将cstring文本分配给动态创建的cstring?

正确的“填充”字符串的方法是:

 strcpy(test3, "abcd"); 
但是,我强烈建议您不要使用
malloc
[而且绝对不要使用
(char*)malloc(…)
-因为这可以隐藏一些相当讨厌的bug,它们会跳起来咬你,至少在适当的时候咬你,因为bug确实有这样的倾向-你这么做可能是因为你把你的C代码编译成C++-代码,这是错误的,并且教会了你像这样的坏习惯]


使用
malloc
分配小字符串是对空间的巨大浪费。您的5个字符字符串的开销可能为16-32字节,并将四舍五入为8或16字节。因此,总共可以使用48个字节来存储5个字节,这是一个很大的空间浪费。

在您的情况下,不能用“=”来分配字符串值

您需要使用strcpy或sprintf函数。在程序结束时(或字符串不再使用时),不要忘记释放它! 例如:

#define BUFSIZE 5

int main(void) {
    char *test3 = malloc(sizeof(char) * BUFSIZE);
    snprintf(test3,BUFSIZE,"test");
    printf("%s\n", test3);
    free(test3);
    return 0;
}
或者你可以写:

int main(void) {
    char buf[BUFSIZE] = "test";
    printf("%s\n", buf);
    return 0;
}
其他人(正确地)建议您将字符串复制到分配的内存中

这就是为什么您的方法是segfaulting:字符串“asdf”是一个字符串文本,在编译时它存储在rodata或只读数据中。当您的程序尝试

test3 = "asdf";
它尝试创建指向rodata的指针。C不允许指向rodata的指针,因此您的语句不仅不起作用,而且存在seg错误


第二个方法很好,因为您没有修改指针,而是修改它指向的对象

首先,谢谢你提出这个问题,它有一个有趣的皱纹

我用Eclipse/MicrosoftC运行了您的代码,没有出现分段错误,它按预期打印了“asdf”

但是,这并不意味着或暗示您没有遇到分割错误。您的结果意味着检查编译器如何实现这两条语句:

   char *test3 = (char *) malloc(sizeof(char) * 5);
在堆上分配存储并设置指向该位置的指针
test3
。 下一条语句也会更新相同的指针

   test3 = "asdf";
但是,在本例中,
test3
指向存储该文本的文本“asdf”。某些编译器生成字符串的文本池并将其存储在可执行文件中的某个位置,因此对于某些编译器,这些文本无法修改

那么,为什么编译器会在无法访问的地方存储一个文本呢?没有意义,因此问题是:您使用的是什么C编译器?它遵循的是什么版本的C

要解决可能存在的编译器错误,并且仍然指向
test3
,请尝试??(同样,C编译器在实现语言构造的内容和方式上存在差异。)


最后,在第二个示例中,堆上
malloc
ed的存储正在被修改,并且显然是可寻址的。

您确定第一个代码示例被正确复制,因为它看起来不会崩溃。。。也许在您的示例中,您所做的不是将常量复制到
test3
——例如,尝试更改
test3
的内容?或者你的意思是当你尝试释放
test3
时它崩溃了吗?我很惊讶你甚至可以用现代编译器做第一个示例,并且禁止你将常量地址分配给非常量指针。您的第一个示例还通过覆盖下一行返回的地址泄漏了您在第一行分配的内存。也就是说,你在两行短线中泄露了内存。我同意Matt的观点,在第一个示例中的代码之后,您可能会在
free()
调用上崩溃,因为您正在释放常量内存。
  const char *literal = "asdf";  // also try without a const stmt 
  // other code here
  test3 = literal;