双指针与指针数组(**数组与*数组[])

Double pointer vs array of pointers(**array vs *array[])

我不清楚这两个之间有什么区别。我的教授写道 **array 与 *array[] 相同,我们看到了一个他使用 **array 的例子(所以在 classes 我试着用 *array[] 交换它但没有用),谁能告诉我这两个是否真的和他写的一样?无论如何,class 是关于动态内存分配的

@我一改双指针,这一行就开始报错

    lines = malloc(sizeof(char*));

和其他一些正在重新分配内存的地方

@2 见鬼,这是完整的代码

对于下面的评论,不,[] 里面什么也没有,因为他的陈述是

    **array = *array[]

重大更新

对于给您带来的不便,我深表歉意,写这篇文章时我实在是太累了post,这是完整的代码,没有任何修改

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    char **lines;     // global text buffer, organized as an array of lines

    // --------------------------------------------------------------------------------
    // initialize global buffer
    void initialize()
    {
      lines = malloc(sizeof(char*));
      lines[0] = NULL;
    }

    // --------------------------------------------------------------------------------
    // return number of lines in buffer
    int countLines()
    {
      int count = 0;
      while(lines[count++]) ;
      return count-1;
    }

    // --------------------------------------------------------------------------------
    // print one line
    void printLine(int line)
    {
      printf("Line %d: %p %p %s\n",line, &lines[line], lines[line], lines[line]);
    }

    // --------------------------------------------------------------------------------
    // print all lines
    void printAll()
    {
      int num_lines = countLines();
      int line = 0;
      printf("----- %d line(s) ----\n",num_lines);
      while (line < num_lines)
        printLine(line++);
      printf("---------------------\n");
    }

    // --------------------------------------------------------------------------------
    // free whole buffer
    void freeAll()
    {
      int line = countLines();
      while (line >= 0)
        free(lines[line--]);
      free(lines);
    }

    // --------------------------------------------------------------------------------
    // insert a line before the line specified
    void insertLine(int line, char *str)
    {
      int num_lines = countLines();

      // increase lines size by one line pointer:
        lines = realloc(lines, (num_lines+2) * sizeof(char*));

      // move line pointers backwards:
      memmove(&lines[line+1], &lines[line], (num_lines-line+1)*sizeof(char*));

      // insert the new line:
      lines[line] = malloc(strlen(str)+1);
      strcpy(lines[line],str);
    }

    // --------------------------------------------------------------------------------
    // remove the specified line
    void removeLine(int line)
    {
      int num_lines = countLines();

      // free the memory used by this line:
      free(lines[line]);

      // move line pointers forward:
      memmove(&lines[line], &lines[line+1], (num_lines-line+1)*sizeof(char*));

      // decrease lines size by one line pointer:
        lines = realloc(lines, num_lines * sizeof(char*));
    }

    // --------------------------------------------------------------------------------
    // insert a string into specified line at specified column
    void insertString(int line, int col, char *str)
    {
      // make room for the new string:
      lines[line] = realloc(lines[line], strlen(lines[line])+strlen(str)+1);

      // move characters after col to the end:
      memmove(lines[line]+col+strlen(str), lines[line]+col, strlen(lines[line])-col);

      // insert string (without terminating 0-byte):
      memmove(lines[line]+col, str, strlen(str));
    }

    // --------------------------------------------------------------------------------
    // MAIN program
    int main()
    {
      initialize();

      printAll();
      insertLine(0,"Das ist");
      printAll();
      insertLine(1,"Text");
      printAll();
      insertLine(1,"ein");
      printAll();
      insertLine(2,"kurzer");
      printAll();
      printf("lines[2][4] = %c\n",lines[2][4]);
      insertString(2,0,"ziemlich ");
      printAll();
      removeLine(2);
      printAll();

      freeAll();
      return 0;
    }

My professor wrote that **array is same as *array[]

这在某些情况下是正确的,而在其他情况下则不然。

如果在函数中用作参数,

void foo(int **array) {}

相同
void foo(int *array[]) {}

声明为变量时,

int **array;

不一样
int *array[];

如果你在问题中引用的代码是你的教授给你的,作为使用指向指针的指针数组的示例,我不确定 class 实际上会有多大用处做。我怀疑它要么作为调试练习提供,要么可能是您尝试解决问题。无论如何,如果您只是在启用 Warnings 的情况下进行编译,在继续调试代码之前,您会发现许多需要注意的问题。

关于您引用的代码,虽然您可以自由使用全局文本缓冲区,但不使用全局缓冲区并根据需要传递指向数据的指针会更好。有一些实例、各种回调函数等需要全局数据,但根据经验,这些都是例外而不是规则。

你的问题基本上可以归结为“如何正确使用指针数组和双指针(指针到指针到类型)变量。一个主题无法完全涵盖回答是因为有太多的情况和上下文可以(或应该)使用其中一个或另一个以及为什么。但是,一些示例有望帮助您理解基本差异。

从指向类型(例如char *array[])的指针数组开始。它通常以这种形式被视为函数参数。当声明为变量时,它后面跟着一个初始化。例如:

char *array[] = { "The quick",
                  "brown fox",
                  "jumps over",
                  "the lazy dog." };

char *array[]; 作为变量声明本身是无效的,因为 [..] 之间缺少数组大小。当全局使用时,如您的示例所示,编译器将接受声明,但会 警告 该声明假定具有 一个元素 .

上面声明的array的元素是指向char类型的指针。具体来说,这些元素是指向由声明创建的 string-literals 的指针。 array 中的关联指针可以访问每个字符串,如 array[0], ... array[3].

A pointer to pointer to pointer to type (double-pointer),顾名思义。它是一个指针,将一个指针作为其值。简单来说,它是一个指向另一个指针的指针。它可以通过分配array的地址来访问上面数组的成员,如:

char **p = array;

其中 p[1]*(p + 1) 指向 "brown fox",等等

或者,可以动态分配多个指向类型的指针并用于创建指向类型的指针数组,然后可以分配和重新分配该数组以处理未知数量元素的访问或存储。例如,一个从 stdin 中读取未知行数的简短示例,您可能会看到:

#define MAXL 128
#define MAXC 512
...
char **lines = NULL;
char buf[MAXC] = {0};
lines = malloc (MAXL * sizeof *lines);
size_t index = 0;
...
while (fgets (buf, MAXC, stdin)) {
    lines[index++] = strdup (buf);
    if (index == MAXL)
        /* reallocate lines */
}

上面有 lines,一个指向字符的指针,最初是 NULL,用于分配 MAXL (128) 个指向字符的指针.然后从 stdin 读取行到 buf,每次成功读取后,分配内存以保存 buf 的内容,并将每个内存块的起始地址分配给每个指针line[index] 其中 index0-127,并且在 index 增加到 128 时,重新分配 index 以提供额外的指针并继续读取。

使该主题大于任何一个答案都无法处理的原因是 指针数组指向类型指针的指针可以是任何 type。 (intstruct 或作为不同类型的结构成员,或 function,等等...)它们可以用于 linked-lists,在目录列表的 return 中(例如 opendir),或以任何其他方式。它们可以静态初始化、动态分配、作为函数参数传递等等……有太多不同的上下文无法涵盖所有​​内容。但在所有情况下,他们都将遵循此处和此处其他答案以及 Whosebug 上 1,000 多个答案中看到的一般规则。

我将以一个简短的示例作为结尾,您可以使用它来了解数组和双指针的不同基本用法。我在源代码中提供了额外的评论。这只是提供了一些不同的基本用法以及静态声明和动态分配:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void) {

    /* array is a static array of 4 pointers to char, initialized to the 
       4 string-literals that a part of the declaration */
    char *array[] = { "The quick",
                    "brown fox",
                    "jumps over",
                    "the lazy dog." };
    /* p is a pointer-to-pointer-to-char assigned the address of array */
    char **p = array;
    /* lines is a pointer-to-pointer-to-char initialized to NULL, used
       below to allocate 8 pointers and storage to hold 2 copes of array */
    char **lines = NULL;
    size_t narray = sizeof array/sizeof *array;
    size_t i;

    printf ("\nprinting each string-literal at the address stored by\n"
            "each pointer in the array of ponters named 'array':\n\n");
    for (i = 0; i < narray; i++)
        printf (" %s\n", array[i]);

    printf ("\nprinting each string using a pointer to pointer to char 'p':\n\n");
    for (i = 0; i < narray; i++, p++)
        printf (" %s\n", *p);

    p = array;
    printf ("\nprinting each line using a pointer to pointer"
            " to char 'p' with array notation:\n\n");
    for (i = 0; i < narray; i++)
        printf (" %s\n", p[i]);

    /* allocate 8 pointers to char */
    lines = malloc (2 * narray * sizeof *lines);

    /* allocate memory and copy 1st 4-strings to lines (long way) */
    for (i = 0; i < narray; i++) {
        size_t len = strlen (array[i]);
        lines[i] = malloc (len * sizeof **lines + 1);
        strncpy (lines[i], array[i], len);
        lines[i][len] = 0;
    }

    /* allocate memory and copy 1st 4-strings to lines 
       (using strdup - short way) */
    // for (i = 0; i < narray; i++)
    //     lines[i] = strdup (array[i]);

    /* allocate memory and copy again as last 4-strings in lines */
    p = array;
    for (i = 0; i < narray; i++, p++)
        lines[i+4] = strdup (*p);

    p = lines; /* p now points to lines instead of array */
    printf ("\nprinting each allocated line in 'lines' using pointer 'p':\n\n");
    for (i = 0; i < 2 * narray; i++)
        printf (" %s\n", p[i]);

    /* free allocated memory */
    for (i = 0; i < 2 * narray; i++)
        free (lines[i]);
    free (lines);

    return 0;
}

如果您有任何问题,请告诉我。这是一个包含相对较少规则集的大主题,可以以多种不同的方式应用在不同的上下文中。