c - 双指针 vs 指针数组(**array vs *array[])

标签 c pointers multidimensional-array dynamic-memory-allocation

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

@一旦我改变了双指针,这一行就开始抛出错误

    lines = malloc(sizeof(char*));

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

@2 是的,这是整个代码

对于下面的那些评论,不,[] 里面没有任何东西,因为他的声明是
    **array = *array[]

大更新

很抱歉给您带来不便,写这篇文章的时候我太累了,这里是没有编辑的完整代码
    #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;
    }

最佳答案

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

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

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

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

char *array[] = { "The quick",
                  "brown fox",
                  "jumps over",
                  "the lazy dog." };
char *array[];由于 [..] 之间缺少数组大小,变量声明本身是无效的.当全局使用时,如在您的示例中,编译器将接受声明,但会警告声明假定具有一个元素。
array的元素上面声明的是指向 char 类型的指针。具体来说,元素是指向由声明创建的字符串文字的指针。每个字符串都可以通过 array 中的关联指针访问。如 array[0], ... array[3] .

指向类型指针(双指针)的指针,正如它的名字所暗示的那样。它是一个指针,持有一个指针作为它的值。从根本上讲,它是一个指向另一个指针的指针。可以通过分配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 等...)它们可以用于链接列表,返回目录列表(例如 opendir ) ,或以任何其他方式。它们可以被静态初始化、动态分配、作为函数参数传递等等......有太多不同的上下文来涵盖它们。但在所有情况下,他们都将遵循此处和此处的其他答案以及 StackOverflow 上的 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;
}

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

关于c - 双指针 vs 指针数组(**array vs *array[]),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33746434/

相关文章:

c++ - 指向类创建错误核心转储的指针

c++ - 指针变量和引用变量有什么区别?

php - 将 mysql_fetch_array 结果转储到多维数组中

计算简单排序程序中的比较和交换

c - 简单的 C 代码在 HPUX 上运行良好,但在 Linux 上会出现段错误。为什么?

c - C 中的简单缓冲区溢出

c - 如何在 ANSI C 中编写文档注释?

c - 如何在 libcurl 中使用 CURLINFO_PRIVATE 访问结构?

python - 初始化可变大小的二维数组

c - 为什么这些循环会奇怪地增加?