【问题标题】:Change value in pointer string array in C在C中更改指针字符串数组中的值
【发布时间】:2015-04-29 14:29:50
【问题描述】:

是否可以通过这种方式更改由字符串指针初始化的字符数组中的值:

char *word;
word = (char*) malloc(10 * sizeof(char));
word = "Test";
word[2] = 'w';

return 0;

执行上述代码时出现分段错误。

【问题讨论】:

  • 欢迎来到 Stack Overflow!警告:你should not cast malloc 的回归。第二个警告:当在malloc(等)you should always write it 中调用sizeofptr = malloc(sizeof(*ptr) * ...); 而不是ptr = malloc(sizeof(ptrtype*) * ...);
  • word = "Test"; 将字符串litteral "Test" 的地址分配给word,首先用malloc 覆盖你在其中得到的内容。你似乎根本不知道自己在做什么,也许应该得到一本关于 C 编程的好教程或好书
  • 您可能必须这样做,或者您可能会search how to do it,然后尝试what you found is supposed to work

标签: c arrays string pointers malloc


【解决方案1】:

你会因为你这样做而崩溃:

word = "Test";
word[2] = 'w';

第一个赋值改变指针,所以它不再指向你分配的内存,而是一个字符串字面量。字符串文字实际上是只读字符数组。由于它们是只读的,因此您在第二次赋值中修改数组的尝试将导致 undefined behavior

正确的方法是将字符串复制到你分配的内存中,你可以使用strcpy函数:

strcpy(word, "test");

重新分配指针的另一件事是,您随后会丢失指向已分配内存的指针,并发生内存泄漏。你也不能在指针上调用free,因为word指向的内存(在你原来的重新分配之后)不再由你分配,这会导致另一种未定义的行为。

【讨论】:

  • 最后一个问题。如果“Test”是字符串文字,如果数组是由标准数组声明字[]声明的,为什么我可以更改它?我想捕捉这两个声明的内部表示。
  • @morophla 因为你创建了一个本地数组,你可以像任何其他本地变量一样修改它。
  • 那么声明 "char word[] = "Test" 就像一个 strcpy?字符串文字是这样复制到数组第一个元素的地址的吗?
【解决方案2】:

第 1 点

您没有在malloc() 之后分配字符串。否则,您将泄漏内存。请改用strcpy()

另外,请do not castmalloc()和family的返回值。

第 2 点

[没有malloc()] 字符串字面量(这里是"Test")通常存储在只读存储器中。尝试更改它们将调用undefined behaviour

参考:根据C11 标准,第 §6.4.5 章,字符串文字,(强调我的)

如果这些数组的元素具有适当的值,则未指定这些数组是否不同。 如果程序尝试修改这样的数组,则行为未定义。

在您的代码中,

word[2] = 'w';

正在尝试更改 字符串文字。而分段错误是UB的副作用之一。

【讨论】:

    【解决方案3】:

    你的代码有很多问题。

    • 您应该never cast the result of malloc,因为这样做是没有意义的并且有潜在的危险。
    • 在 C 中,您使用 strcpy() 复制字符串,而不是使用赋值运算符 =。
    • 由于您从未复制字符串,只是告诉指针指向其他位置,因此造成了内存泄漏。
    • 而且由于您从未复制字符串,而只是指向字符串文字,因此您会调用未定义的行为,因为您尝试修改字符串文字的内容。 (删除 malloc 行,您仍然会遇到此错误。)
    • 您似乎没有释放()内存,也没有检查 malloc 的返回值。

    正确代码:

    char* word;
    word = malloc(10);
    if(word == NULL)
    {
      // out of memory, error handling here
    }
    
    strcpy(word, "Test");
    word[2] = 'w'; // should give "Tewt"
    ...
    free(word);
    

    【讨论】:

    • 所以你说我们不应该在 C 中强制转换 malloc。但在 C++ 中强制转换是强制性的,对吧?
    • @morophla 是的。语言不兼容的许多情况之一。这并不重要,因为无论如何你都不应该在 C++ 中使用 malloc。
    【解决方案4】:

    您的代码 sn-p 应该看起来更像这样:

    int maxlen = 10;
    char *word;
    word = malloc(maxlen * sizeof(char));
    strncpy(word, "Test", maxlen);
    word[2] = 'w';
    
    return 0;
    

    【讨论】:

    • 那么在初始化像word[] = "Test"这样的数组时,是不是意味着字符串字面量的内容被复制到了数组中,或多或少像strcpy?
    • @morophia 您可以执行char word[] = "Test";,它将在堆栈(而不是堆)上分配内存,并使用给定的字符串初始化 char 数组。但是字符串必须在编译时知道。
    【解决方案5】:

    这取决于。如果指针指向字符串文字,则不能。如果它是一个字符数组,那么它是可能的。

    在给定的 sn-p 中,您使用 mallocword 分配内存,然后将字符串文字分配给 word,这让 word 指向 Test 的第一个字符和前一个字符它不再指向分配的内存,这将导致内存泄漏。在这种情况下,您不能通过word[2] = 'w'; 修改Test。它将调用未定义的行为。

    代替word = "Test";,使用strcpy复制字符串

    strcpy(word, "Test");  
    

    【讨论】:

      【解决方案6】:

      1) 指针是 'word' 正在被替换。 这会导致内存泄漏

      2) 文字在只读内存中, 因此尝试更改该内存中的任何内容都会导致段错误事件

      【讨论】:

      • 那么在初始化像word[] = "Test"这样的数组时,是不是意味着字符串字面量的内容被复制到了数组中,或多或少像strcpy?
      猜你喜欢
      • 2018-05-06
      • 2021-06-28
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多