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

时间:2015-11-16 23:17:16

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

我不清楚这些之间的区别是什么2.我的教授写道**数组与* array []相同,我们得到了一个例子,他使用了**数组(因此在课后我尝试与之交换) * array []并且它没有工作),有谁能告诉我这些2是否与他写的一样?无论如何,这个类是关于动态内存分配的

@当我更改双指针时,此行开始抛出错误

    lines = malloc(sizeof(char*));

以及其他一些内存重新分配的内容

@ 2地狱呀,这里是整个代码

对于那些评论,但是,因为他的陈述是

,所以内部没有任何内容
    **array = *array[]

BIG UPDATE

对于给您带来的任何不便,我感到非常抱歉,在写这篇文章的时候我太累了,这里是没有编辑的整个代码

    #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;
    }

2 个答案:

答案 0 :(得分:11)

如果你的问题中提到的代码是由你的教授给你的,作为使用指针指针数组的一个例子,我不确定该类实际上会做多少好事。我怀疑它是作为调试练习提供的,或者可能是您尝试解决方案。无论如何,如果您只是在启用警告的情况下进行编译,那么在进行调试代码之前,您会发现许多需要注意的问题。

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

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

指向的指针数组开始(例如char *array[])。通常以该形式将其视为函数参数。声明为变量时,会进行初始化。 e.g:

char *array[] = { "The quick",
                  "brown fox",
                  "jumps over",
                  "the lazy dog." };
由于char *array[];之间缺少数组大小,

[..]本身作为变量声明无效。当全局使用时,如在您的示例中,编译器将接受声明,但警告声明假定一个元素

上面声明的array元素是指向char类型的指针。具体来说,元素是指向由声明创建的 string-literals 的指针。每个字符串都可以由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,一个指向char的指针,最初是NULL,用于分配MAXL(128)指针到char。然后从stdin读取行到buf,每次成功读取后,分配内存以保存buf的内容,并为每个指针分配每个内存块的结果起始地址line[index] index 0-127 indexindex增加到128,重新分配type以提供其他指针并继续阅读。

使主题大于可以在任何一个答案中处理的主题是指针数组指向类型指针的指针可以是任何{{1} }。 (intstruct,或作为不同类型的结构的成员,或function等...)可以使用链接列表 ,返回目录列表(例如opendir),或以任何其他方式返回。它们可以静态初始化,动态分配,作为函数参数传递等等......有太多不同的上下文来覆盖它们。但是在所有情况下,他们都会遵循这里和其他答案中的一般规则,并且在StackOverflow上有1000多个答案。

我将以一个简短的示例结束,您可以使用它来查看数组和双指针的不同基本用法。我在源代码中提供了其他评论。这仅提供了一些不同的基本用法以及静态声明和动态分配:

#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;
}

如果您有任何疑问,请与我们联系。这是一个规模相对较小的大型主题,可以在不同的方式和不同的环境中应用。

答案 1 :(得分:8)

  

我的教授写道**array*array[]

相同

在某些情况下也是如此,在其他情况下则不然。

如果在函数中用作参数,

void foo(int **array) {}

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

当声明为变量时,

int **array;

不同
int *array[];

免责声明:这绝不是一份详尽的清单,列出了它们在哪里以及它们的不同之处。