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



以下代码总是分段故障:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3 = "asdf";
  printf("%sn", test3);

以下代码未分段故障:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3[0] = 'a';
  test3[1] = 'b';
  test3[2] = 'c';
  test3[3] = 'd';
  test3[4] = '';
  printf("%sn", test3);

我想问题可能是如何将cstring文字分配给动态创建的cstring?

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

 strcpy(test3, "abcd"); 

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

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

其他人(正确地)建议您将字符串复制到分配的内存中。

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

test3 = "asdf";

它试图创建一个指向rodata的指针。C不允许指针指向rodata,因此您的语句不仅不起作用,而且还会出现seg错误。

第二种方法很好,因为您不是在修改指针,而是在修改它指向的内容。

首先,感谢您提出这个问题——它有一个有趣的褶皱。

我用Eclipse/Microsoft C运行了您的代码,但没有得到分段错误,它按预期打印了"asdf"。

然而,这并不意味着或暗示你没有得到一个分割错误。您的结果意味着要检查编译器如何实现以下两个语句:

   char *test3 = (char *) malloc(sizeof(char) * 5);

在堆上分配存储,并将指针test3设置为指向该位置。下一条语句还会更新相同的指针。

   test3 = "asdf";

然而,在这种情况下,test3指向存储该文本的文本"asdf"。有些编译器生成字符串的文本池,并将其存储在可执行文件中的某个位置,因此对于某些编译器来说,这些文本是无法修改的。

那么,编译器为什么要将文字存储在无法访问的地方呢?没有意义,因此问题来了:你用的是什么C编译器?它坚持什么版本的C??

要解决可能是编译器错误的问题,并且仍然将test3指向文字,请尝试??(同样,C编译器在实现语言结构的内容和方式上确实有所不同。)

  const char *literal = "asdf";  // also try without a const stmt 
  // other code here
  test3 = literal;

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

在您的情况下,不能用"="分配字符串值。

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

#define BUFSIZE 5
int main(void) {
    char *test3 = malloc(sizeof(char) * BUFSIZE);
    snprintf(test3,BUFSIZE,"test");
    printf("%sn", test3);
    free(test3);
    return 0;
}

或者你可以写:

int main(void) {
    char buf[BUFSIZE] = "test";
    printf("%sn", buf);
    return 0;
}

相关内容

  • 没有找到相关文章

最新更新