【问题标题】:Assigning memory to double pointer?将内存分配给双指针?
【发布时间】:2011-01-16 11:54:16
【问题描述】:

我无法理解如何分配内存 到一个双指针。 我想读取一个字符串数组并存储它。

    char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<20; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

我只是分配了一大块内存而不是这个 存储字符串

  char **ptr;
  ptr = (char**)malloc(sizeof(char)*50*50);

那会是错的吗?如果是这样,为什么会这样?

【问题讨论】:

  • 不要称它为“双指针”——这会让你在精神上走错路——它是指向指针的指针。
  • 在 C 中,不要将调用结果转换为 malloc()realloc()calloc() - 这是不必要的,并且可能掩盖了缺少原型的严重错误。

标签: c string pointers malloc double-pointer


【解决方案1】:

您的第二个示例是错误的,因为从概念上讲,每个内存位置都不会保存char*,而是char。如果你稍微改变一下你的想法,它会有所帮助:

char *x;  // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'

x = (char*)malloc(sizeof(char) * 100);   // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'

// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'

因此,您的第一个循环将是您如何在 C 中执行字符数组/指针数组。对字符数组的数组使用固定的内存块是可以的,但您可以使用单个 char* 而不是 char**,因为内存中没有任何指针,只有 chars。

char *x = calloc(50 * 50, sizeof(char));

for (ii = 0; ii < 50; ++ii) {
    // Note that each string is just an OFFSET into the memory block
    // You must be sensitive to this when using these 'strings'
    char *str = &x[ii * 50];
}

【讨论】:

  • 最后一行不应该是char *str = x+(ii*50)吗?
  • 并且不要投射malloc()的结果!
【解决方案2】:
 char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<50; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

fclose(fp);

可能是您的拼写错误,但如果您正在寻找 50 x 50 矩阵,您的循环应该是 50 而不是 20。此外,在上述内存分配之后,您可以以 ptr[i][j] 的形式访问缓冲区,即 2D 格式。

【讨论】:

    【解决方案3】:

    双指针只是指向另一个指针的指针。所以你可以这样分配它:

    char *realptr=(char*)malloc(1234);
    char **ptr=&realptr;
    

    您必须记住指针的存储位置(在此示例中,双指针指向堆栈上的指针变量,因此在函数返回后它无效)。

    【讨论】:

      【解决方案4】:

      我会举一个例子,这可能会消除疑问,

      char **str;                              // here its kind a equivalent to char *argv[]
      str = (char **)malloc(sizeof(char *)*2)  // here 2 indicates 2 (char*)
      str[0]=(char *)malloc(sizeof(char)*10)   // here 10 indicates 10 (char)
      str[1]=(char *)malloc(sizeof(char)*10)   // <same as above>
      
      strcpy(str[0],"abcdefghij");   // 10 length character 
      strcpy(str[1],"xyzlmnopqr");   // 10 length character
      
      cout<<str[0]<<endl;    // to print the string in case of c++
      cout<<str[1]<<endl;    // to print the string in case of c++
      
      or
      
      printf("%s",str[0]);
      printf("%s",str[1]);  
      
      //finally most important thing, dont't forget to free the allocated mem
      free(str[0]);
      free(str[1]);
      free(str);
      

      【讨论】:

        【解决方案5】:

        其他更简单的记忆方法

        案例-1:

        第 1 步:字符 *p;

        步骤-2: 请按如下方式阅读

        字符 (*p); ==> p 是一个指向字符的指针

        现在你只需要为没有大括号的类型(步骤 2)做 malloc

        即 p = malloc(sizeof(char) * some_len);

        案例-2:

        第 1 步:字符 **p;

        步骤-2:

        请按如下方式阅读

        char* (* p); ==> p 是一个指向 char *

        现在你只需要为没有大括号的类型(步骤 2)做 malloc

        即 p = malloc(sizeof(char *) * some_len);

        案例-3:

        没有人用这个,只是为了解释

        字符***p;

        读作,

        字符** (*p); ==> p 是一个指向 char** 的指针(对于上面的这个检查 case-2)

        p = malloc(sizeof(char**) * some_len);

        【讨论】:

          【解决方案6】:

          添加到 Pent 的答案中,正如他正确指出的那样,一旦函数返回,您将无法使用此双指针,因为它将指向函数在堆栈上的激活记录上的内存位置,该位置现在已过时(曾经函数已返回)。如果你想在函数返回后使用这个双指针,你可以这样做:

          char * realptr = (char *) malloc(1234);
          char ** ptr = (char **) malloc(sizeof(char *));
          *ptr = realptr;
          return ptr;
          

          这个函数的返回类型显然必须是char **

          【讨论】:

            【解决方案7】:

            双指针,简单来说就是一个指向指针的指针, 在许多情况下,它被用作其他类型的数组。

            例如,如果你想创建一个字符串数组,你可以这样做:

            char** stringArray = calloc(10, 40);
            

            这将创建一个大小为 10 的数组,每个元素将是一个长度为 40 的字符串。

            因此您可以通过 stringArray[5] 访问它并在第 6 位获得一个字符串。

            这是一种用法,其他的如前所述,一个指向指针的指针,可以通过以下方式简单分配:

            char* str = (char*)malloc(40);
            char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.
            

            在这里阅读更多: good array tutorial

            【讨论】:

            • 不,这会创建一个包含 100 个 char* 的数组,假设 char* 占用 4 个字节。
            • 汉斯说的是对的。更重要的是,100 个 char* 的数组被初始化为 0(因为您使用了 calloc),所以所有这些 char* 都指向 null 并且访问该数组位置会导致错误。
            猜你喜欢
            • 2021-03-18
            • 1970-01-01
            • 1970-01-01
            • 2021-04-13
            • 1970-01-01
            • 2021-05-07
            • 2011-02-23
            • 1970-01-01
            • 2013-12-10
            相关资源
            最近更新 更多