双指针VS指针数组(**阵VS * []数组) [英] Double pointer vs array of pointers(**array vs *array[])

查看:202
本文介绍了双指针VS指针数组(**阵VS * []数组)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

林没有明确肯定是我的教授写道:**阵列是一样的* []数组,我们被presented在那里他用一个例子**阵列(让班后,我想这些2之间的区别交换与* []数组,它不工作),任何人都可以告诉我,如果这2实际上是为他写的一样?反正类是关于动态内存分配

@as只要我换了双指针,这条线开始呕吐误差

  =行的malloc(sizeof的(字符*));

和其他几个人,其中内存重新分配beeing

@ 2地狱啊,这里是整个code

和波纹管对于这些意见,没了里面有[]没有什么,因为他的声明是

  **阵列= * []数组

大更新

我的任何不便,非常抱歉,我在写这篇文章的时候只是太累了,这里是整个code没有修改

 的#include<&stdio.h中GT;
    #包括LT&;&stdlib.h中GT;
    #包括LT&;&string.h中GT;    焦炭**线; //全局文本缓冲区,组织成线阵列    // ------------------------------------------------ --------------------------------
    //初始化全局缓冲区
    void初始化()
    {
      线=的malloc(sizeof的(字符*));
      行[0] = NULL;
    }    // ------------------------------------------------ --------------------------------
    //返回缓冲区行数
    诠释countLines()
    {
      诠释计数= 0;
      而(行[统计++]);
      返回计数-1;
    }    // ------------------------------------------------ --------------------------------
    //打印一行
    无效printLine(INT线)
    {
      的printf(%d行:%P%P%S \\ n,行,和放大器;线[线],线[线],线[线]);
    }    // ------------------------------------------------ --------------------------------
    //打印所有行
    无效printAll()
    {
      INT NUM_LINES = countLines();
      INT行= 0;
      的printf(-----%D线(S)---- \\ n,NUM_LINES);
      而(线474; NUM_LINES)
        printLine(行++);
      的printf(--------------------- \\ n);
    }    // ------------------------------------------------ --------------------------------
    //自由整个缓冲区
    无效freeAll()
    {
      INT线= countLines();
      而(行GT; = 0)
        免费(行[line--]);
      免费(线);
    }    // ------------------------------------------------ --------------------------------
    //指定的行前插入一行
    无效insertLine(INT线,字符*海峡)
    {
      INT NUM_LINES = countLines();      //增加线的大小由一行指针:
        线=的realloc(线,(NUM_LINES + 2)* sizeof的(字符*));      //招行指针向后:
      memmove与(安培;线[在线+ 1],&安培;线[线],(NUM_LINES线+ 1)* sizeof的(字符*));      //插入新行:
      行[行] =的malloc(strlen的(STR)+1);
      的strcpy(行[线],STR);
    }    // ------------------------------------------------ --------------------------------
    //删除指定的行
    无效removeLine(INT线)
    {
      INT NUM_LINES = countLines();      //释放由该行所使用的内存:
      免费(行[行]);      //招行指针向前:
      memmove与(安培;线[线],和放大器;线[在线+ 1],(NUM_LINES线+ 1)* sizeof的(字符*));      //针线大小由一行指针:
        线=的realloc(线,NUM_LINES * sizeof的(字符*));
    }    // ------------------------------------------------ --------------------------------
    //在指定列插入一个字符串到指定的行
    无效insertString(INT线,诠释关口,字符*海峡)
    {
      //腾出空间给新的字符串:
      行[行] = realloc的(行[线],strlen的(行[线])+ strlen的(STR)+1);      //山坳到结束后的移动字符:
      memmove与(行[行] + COL +的strlen(STR),线[线] +关口,strlen的(行[线]) - COL);      //插入的字符串(不终止0字节):
      memmove与(行[行] +关口,STR,strlen的(STR));
    }    // ------------------------------------------------ --------------------------------
    //主程序
    诠释的main()
    {
      初始化();      printAll();
      insertLine(0,达斯IST);
      printAll();
      insertLine(1,文字);
      printAll();
      insertLine(1,EIN);
      printAll();
      insertLine(2,kurzer);
      printAll();
      的printf(行[2] [4] =%C \\ n,行[2] [4]);
      insertString(2,0ziemlich);
      printAll();
      removeLine(2);
      printAll();      freeAll();
      返回0;
    }


解决方案

如果你在你的问题中引用code的给你用你的教授作为使用指针的指针数组的指针的例子,我不太确定该类多少好处会怎么做。我怀疑它可能提供一个锻炼的调试,也可能是你的一个解决方案的尝试。无论如何,如果你只是使用的警告编译的启用,你会发现一些则进入调试code之前需要注意的问题。

对于您参考,而你可以自由使用一个全局文本缓冲区code,你是远通过不使用全局缓冲区,指针传递到您的数据需要更好的服务。有一些情况下,各种各样的回调函数等需要全球的数据,但作为一个经验法则,这些是例外,而不是规则。

您的问题基本上可以归结为如何正确使用指针,双指针(指针到指针到型)的变量数组。没有办法的话题完全可以覆盖一个答案,因为有在其中一个或其他的都可以(或应该)使用,这是为什么。但是,有少数的例子希望能帮助你了解基本的分歧太多的情况和环境。

与启动的指针数组键入的(例如的char *数组[] )。它通常被以这样的形式作为函数参数。当作为一个变量声明它后面与初始化。例如:

 的char *数组[] = {快速,
                  棕色狐狸
                  跳过
                  懒惰的狗。 };

的char * []数组; 本身作为一个变量的声明是无效的,由于之间缺少数组的大小[..] 。当全球范围内使用,因为在你的榜样,编译器将接受申报,但会的警告的声明被认为具有的的元素

阵列的元素上述声明是指向char类型。具体地,元件是指针指向的字符串文字的由该声明创建。字符串的每一个都可以通过相应的指针数组访问数组[0],...阵列[3]

A 指针指向类型的(双指针),正是它的名字所暗示的。这是一个的指针的,持有的指针的是它的价值。在基本方面,它是指向另一个指针的指针。它可用于以上通过分配的地址访问数组的成员阵列这样的:

 的char ** P =阵列;

其中, P [1] *(P + 1)棕色狐狸

替代地,一些指针以指向类型可以被动态分配和使用,以创建指针数组键入,则可以分配和重新分配给处理的未知数量的元素的访问或存储。例如一个简单的例子来读取标准输入未知的行数,您可能会看到:

 的#define MAXL 128
#定义MAXC 512
...
焦炭**线= NULL;
焦炭BUF [MAXC] = {0};
线=的malloc(MAXL * sizeof的*线);
为size_t索引= 0;
...
而(与fgets(BUF,MAXC,标准输入)){
    行[指数++] =的strdup(BUF);
    如果(指数== MAXL)
        / *重新分配行* /
}

在上面,你有,指针到指针到字符,最初 NULL ,即使用分配 MAXL (128)的指针到字符。线,然后从标准输入读入 BUF ,每次成功读取后,内存分配给持有<$的内容C $ C> BUF 所得起始地址存储器的每个块分配给每个指针行[指数] ,其中首页 0-127 ,并在首页 128的增量,首页被重新分配,以提供额外的指针和读继续。

是什么让话题比可以在任何一个答案来处理更大的是,一个的指针数组指针指向类型的可以是任何键入。 ( INT 结构,或作为一个结构到不同类型的成员,或功能,等...),它们可以使用的链接列表的,在目录列表回报(如执行opendir ),或者在方法的任何附加号码。它们可以被静态初始化,动态分配的,因为函数参数传递,等等......只是有太多不同的情况下,以支付他们所有。但是,在所有情况下,他们将按照在这里和这里其他的答案,并在1000的位置在计算器上更多的答案看到的一般规则。

我跟你可以用它来看看阵列和双指针的不同的基本用途很短的例子结束。我在源提供补充意见。这正好提供了不同的基本用途和静态声明和动态分配一把:

 的#include&LT;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;诠释主要(无效){    / *数组的指针4静态数组为char,初始化为
       4字符串常量,该声明的一部分* /
    的char *数组[] = {快速,
                    棕色狐狸
                    跳过
                    懒惰的狗。 };
    / * p是一个指针到指针到指定的字符数组的地址* /
    焦炭** P =阵列;
    / *行是一个指针到指针到字符初始化为NULL,使用
       下面来分配8指针和存储空间来容纳2 COPES数组* /
    焦炭**线= NULL;
    为size_t narray = sizeof的阵列/​​ * sizeof的阵列;
    为size_t我;    的printf(\\ nprinting每个字符串字面的地址由\\ n存储
            名为'阵'ponters阵列中的每个指针:\\ n \\ n);
    对于(i = 0; I&LT; narray;我++)
        的printf(%S \\ N阵列[我]);    的printf(\\使用指针的指针为char'P'nprinting每个字符串:\\ n \\ n);
    对于(i = 0; I&LT; narray;我++,P ++)
        的printf(%S \\ n,* P);    P =阵列;
    的printf(\\ nprinting每一行使用指针的指针
            为char'P'使用数组方式:\\ n \\ n);
    对于(i = 0; I&LT; narray;我++)
        的printf(%S \\ n,P [I]);    / *分配8指针为char * /
    线=的malloc(2 * narray * sizeof的*线);    / *分配的内存和4月1日 - 字符串复制到线(长路)* /
    对于(i = 0; I&LT; narray;我++){
        size_t型LEN = strlen的(数组[我]);
        线[I] =的malloc(LEN * sizeof的**线+ 1);
        函数strncpy(行[I],数组[我],LEN);
        线由[i] [长度] = 0;
    }    / *分配内存和复制月1日4串的行
       (使用的strdup - 短路)* /
    //为(i = 0; I&LT; narray;我++)
    //行[I] =的strdup(数组[我]);    / *分配内存,并在最后行4弦再次复制* /
    P =阵列;
    对于(i = 0; I&LT; narray;我++,P ++)
        线[I + 4] =的strdup(* P);    P =线; / * P现在指向行,而不是数组* /
    的printf(\\ nprinting在'行'使用指针P每个分配行:\\ n \\ n);
    对于(I = 0; I&2 * narray;我+ +)
        的printf(%S \\ n,P [I]);    / *自由分配的内存* /
    对于(I = 0; I&2 * narray;我+ +)
        免费(行[I]);
    免费(线);    返回0;
}

让我知道如果您有任何疑问。它的大主题具有相对小的一套规则,可以在一大堆不同的方式和在不同情况下可以应用

Im not clearly sure what is the difference between those 2. My professor wrote that **array is same as *array[] and we were presented an example where he used **array (so after classes I tried exchanging that with *array[] and it didn't work), could anyone tell me if those 2 are actually the same as he wrote?? Anyway the class was about dynamic memory allocation

@As soon as I changed the double pointer, this line started throwing error

    lines = malloc(sizeof(char*));

and a few others where the memory is beeing reallocated

@2 Hell yeah, here's the whole code

And for those comments bellow, nope there is nothing inside [] because his statement was

    **array = *array[]

BIG UPDATE

I am so sorry for any inconvenience, I was just too tired at the time of writing this post, here is the whole code with no edits

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

解决方案

If the code you reference in your question was given to you by your professor as an example of the use of pointer arrays of pointers to pointers, I'm not sure how much good that class will actually do. I suspect it was either provided as a debugging exercise or it may have been your attempt at a solution. Regardless, if you simply compile with Warnings enabled, you will find a number of problems that need attention before you advance to debugging your code.

Regarding the code you reference, while you are free to use a global text buffer, you are far better served by not using a global buffer, and passing a pointer to your data as required. There are some instances, various callback functions, etc. that require global data, but as a rule of thumb, those are the exception and not the rule.

Your question basically boils down to "How do I properly use array of pointers and double-pointers (pointer-to-pointer-to-type) variables. There is no way the topic can be completely covered in one answer because there are far too many situations and contexts where one or the other can be (or should be) used and why. However, a few examples will hopefully help you understand the basic differences.

Starting with the array of pointers to type (e.g. char *array[]). It is generally seen in that form as a function argument. When declared as a variable it is followed with an initialization. e.g.:

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

char *array[]; by itself as a variable declaration is invalid due to the missing array size between [..]. When used globally, as in your example, the compiler will accept the declaration, but will warn the declaration is assumed to have one element.

The elements of array declared above are pointers to type char. Specifically, the elements are pointers to the string-literals created by the declaration. Each of the strings can be accessed by the associated pointer in array as array[0], ... array[3].

A pointer to pointer to type (double-pointer), is exactly what its name implies. It is a pointer, that holds a pointer as its value. In basic terms it is a pointer that points to another pointer. It can be used to access the members of the array above by assigning the address of array like:

char **p = array;

Where p[1] of *(p + 1) points to "brown fox", etc.

Alternatively, a number of pointer to pointer to type can be dynamically allocated and used to create an array of pointers to type, that can then be allocated and reallocated to handle access or storage of an unknown number of elements. For example a brief example to read an unknown number of lines from stdin, you might see:

#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 */
}

Above you have lines, a pointer-to-pointer-to-char, initially NULL, that is use to allocate MAXL (128) pointers-to-char. Lines are then read from stdin into buf, after each successful read, memory is allocated to hold the contents of buf and the resulting start address for each block of memory is assigned to each pointer line[index] where index is 0-127, and upon increment of index to 128, index is reallocated to provide additional pointers and the read continues.

What makes the topic larger than can be handled in any one answer is that an array of pointers or pointer to pointer to type can be to any type. (int, struct, or as a member of a struct to different type, or function, etc...) They can be used linked-lists, in the return of directory listings (e.g opendir), or in any additional number of ways. They can be statically initialized, dynamically allocated, passed as function parameters, etc... There are just far too many different contexts to cover them all. But in all instances, they will follow the general rules seen here and in the other answer here and in 1,000's more answers here on StackOverflow.

I'll end with a short example you can use to look at the different basic uses of the array and double-pointer. I have provided additional comments in the source. This just provides a handful of different basic uses and of static declaration and dynamic allocation:

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

Let me know if you have any questions. It a large topic with a relatively small set of rules that can be applied in whole lot of different ways and in different contexts.

这篇关于双指针VS指针数组(**阵VS * []数组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆