【问题标题】:Modify string address inside of function修改函数内部的字符串地址
【发布时间】:2015-02-11 20:05:02
【问题描述】:

我在 main() 中有字符串

char *string = NULL;

那我有一个函数

foo(char *s){
    s = realloc( ... );
    ..
}

如果字符串不够长,我想做的是为字符串重新分配内存,所以当我在 main() 中访问这个函数时,我必须把它像 foo(&string)foo(string) 一样吗?

它会在 foo() 函数之外更改s 的地址吗?

【问题讨论】:

标签: c string pointers realloc


【解决方案1】:
  1. 字符串不是指针、数组等。

    C 中的字符串定义为由零元素终止的非零元素序列,除非另有说明类型为 char
    那些字符串通常保存在一个数组中,数组名用于通俗地引用它们。

    因此,您没有main() 中有字符串。

  2. C 是严格按值传递的,这意味着您永远不能修改用于从函数内部初始化函数参数的表达式。

    但它也有指针,因此您可以传递对象的地址来启用修改该对象。

顺便说一句,不要使用过时的隐式int return-type。

综合起来,你有:

#include <string.h> // strcpy
#include <stdlib.h> // realloc free abort
#include <stdio.h>  // puts

void foo(char** sz) {
    const static hw[] = "Hello world!";
    *sz = realloc(*sz, sizeof hw);
    if(!*sz) abort();
    strcpy(*sz, hw);
}

int main() {
    char* sz = 0; // Pointer for a string
    foo(&sz);
    puts(sz);
    free(sz); // Superfluous cleanup
}

【讨论】:

    【解决方案2】:

    您需要传递字符串指针的地址。因为你的“字符串”实际上是一个指向char 的指针,所以你想要一个“指向char 的指针”的东西,写成char **。传递给foo()的时候需要传递指针的地址,所以foo(&amp;string)是正确的。

    当您在函数中引用字符串时,您将需要和“额外”取消引用,例如:

    int n = strlen(*s);
    

    这也适用于重新分配:

    *s = realloc(...);
    

    或者,您可以像往常一样传递它并返回(可能是新的)指针作为函数的值。例如:

    char * foo(char *s)
    {
        if (...)
            s = realloc(...);
        ...
        return s;
    }
    

    当然,这意味着你必须像 main() 中那样调用/使用函数:

    string = foo(string);
    

    【讨论】:

    • 但是如果我有这个函数 foo() 返回 void,所以它什么都不返回,它真的只修改那个字符串 s foo(char *s) { if (...) s = realloc(...); ... } 是正确的吗?
    • 对,main 会看到旧值,因为你在上面调用了realloc(),所以它不再有效
    【解决方案3】:

    您是否检查了 main 函数中完成的 realloc。

    试试这个简单的。

    main()
    {
       char *string;
       string=(char*)malloc(10);
       printf("%p\n",string);
       string=(char*)realloc(string,20);
       printf("%p\n",string);
    }
    

    如果您使用 realloc 重新分配内存。如果在已经分配的内存重新分配后内存中有所需的内存可用,则不会更改内存。只需将所需的内存空间添加到已分配的内存中即可。如果您在大多数情况下使用单个变量,则内存地址不会更改。

    如果你想使用这个函数来获得它。

    char*foo(char*s)              
    {
     s=(char*)realloc(s,20);
     printf("foo:%p\n",s);
     return s;
    }
    

    请参考this

    【讨论】:

      【解决方案4】:

      char* str 是一个变量。这意味着它在内存中获得了一个地址,这个地址的内容(char * str的值)是一个char的地址。

      当你分配内存时,你对char* str感兴趣,所以你可以使用它的内容,因此你把它的地址发送到foo,这样你的代码就变成了这样:

          void foo(char** str) {
          *str = malloc(5*sizeof(char));
          *str = "1234";
      }
      int main() {
          char* str1 = NULL;
          foo(&str1);
          printf("str1 = %s\n", str1);
         return 0;
      }
      

      请注意,这样分配内存是一个坏习惯,因为如果foo 是一个为字符串分配内存并返回该字符串指针(char*)的函数,那么您将无法释放它记忆。

      【讨论】: