Вопрос по c, arrays – Как работает массив указателей на указатели?

6
<code>char **Data[70]={NULL};  
</code>

Какова правильная терминология для этого? Как еще это можно написать? Как это выглядит в памяти? Я читаю много учебников по указателям, но я не вижу его в этом синтаксисе. Любая помощь приветствуется. Благодарю.

Ваш Ответ

5   ответов
1

Это не очень очевидно:

char **Data[70]={NULL};

но с альтернативным объявлением, например:

char* Data[2][3] = {
  {"Nick", "Tom", "Helen"},
  {"one", "two", "three"}
};

мы легко видим, что это двумерный массив строк.

Edit:    Я использовал данные [2] [3], чтобы показать, что это двумерный массив. я использовалfixed размер для таких размеров, как 2 & amp; 3 просто для демонстрации. Конечно, мы можем иметь:

char* Data[][3]={
  {"Nick", "Tom", "Helen"},
  {"one", "two", "three"},
  // ...
};

или жеchar** Data[]

Хорошо, вот что я имею в виду под 2-D массивом:

char** Data[2]={0};

void test()
{
  char* d1[] = {"1", "2"};
  char* d2[] = {"10", "20", "30"};
  Data[0] = d1;
  Data[1] = d2;

  printf("%s\n", Data[0][0]);
  printf("%s\n", Data[0][1]);
  printf("%s\n", Data[1][0]);
  printf("%s\n", Data[1][1]);
  printf("%s\n", Data[1][2]);
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededn pointers, and Data[1][1] is understood by the compiler to refer to the 1*m + 1 th of those. This is why the last, and only the last, dimension of a multi-dimensional array, is "lost" when passed through a function signature. A char*Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded T.T.T.
Error: User Rate Limit Exceeded
2

**. Особенно один с 70 элементами.

Однако предположим, что я собираюсь запустить 70 программ. Как вы, вероятно, знаете, аргументы программы обычно передаются какchar** argv параметр дляmain() (или жеchar*[] argv, что в сигнатуре функции это то же самое). Поэтому, если бы я хотел сохранить указатели argv для всех этих программ, я бы использовал массив так же, какData, Очевидно, что мне также нужно больше памяти в другом месте, чтобы фактические строки и массивы argv занимали, но это начало.

Инициализация массива с{NULL} устанавливает все его элементы в NULL. Это полезное сокращение: вы можете инициализировать массив с{firstelement, secondelement, ...}, но если вы не предоставите достаточно терминов, все остальные будут рассматриваться как 0.

Как и любой другой массив указателей, инициализированных с помощью {NULL}, в памяти это выглядит как 70 указателей NULL, расположенных подряд. Там (как правило) нет никакой разницы в памяти междуchar** и любой другой указатель объекта. Я думаю, что законно написать странную реализацию, в которой есть разница, но не задерживай дыхание, ожидая, чтобы встретить такую.

Итак, разница между 70 NULLchar** подряд и 70 NULLchar* подряд чтоwould находиться на другом конце указателя, если они не равны NULL. На другом концеchar** это указатель на символ На другом концеchar* это символ Указатель или символ могут быть первыми в массиве, в зависимости от того, как он используется.

0

по сути, указатель на указатель на указатели. Тем не менее, поскольку указатель & quot; это не что иное, как место в памяти, в действительности это не имеет большого смысла делать это, чем просто выполнять char * Data [70], кроме того, что очевидно, что каждый char * является указателем на другой char *, а не указателем на голец.

1

То, что вы получили, представляет собой массив из 70 указателей, каждый из которых указывает на другой указатель, каждый из этих указателей указывает на символ. Что интересно, сами массивы являются указателями, поэтому у вас есть три уровня указателей.

Массивы НЕ являются указателями.
24

Эта структура

char **Data[70]={NULL};

это массив из 70 указателей на указатели на char. Компилятор выделяет70 * sizeof(char**) байтов для этого массива, который при условии 32-битных указателей составляет 280 байтов.

Если вы внутренне думаете о «указателе на символ» как строка, которая не является истинной, но достаточно близкой, то это массив из 70 указателей на строки. Чтобы создать ASCII-арт и сделать вид, что вы выделили и заполнили некоторые значения ....

 Array of        One or more
 char **           char *
+---------+     +---------+
|    0    | --> |   ptr   | -->  "Hello, world"
+---------+     +---------+
|    1    |
+---------+       +---------+
|    2    | ----> |  ptr2   | -->  "Goodbye, cruel world"
+---------+       +---------+
|    3    |
+---------+         +---------+
|    4    | ------> | ptr3[0] | -->  "Message 0"
+---------+         +---------+
    ...             | ptr3[1] | -->  "Message 1"
+---------+         +---------+
|   69    |         | ptr3[2] | -->  "Message 2"
+---------+         +---------+

Вы можете сделать это с помощью кода, подобного следующему (проверка ошибок при возврате значений malloc пропускается):

char **Data[70]={NULL};
char **ptr, **ptr2, **ptr3;

ptr = (char **) malloc(sizeof(char *));
*ptr = "Hello, world";
Data[0] = ptr;

ptr2 = (char **) malloc(sizeof(char *));
*ptr2 = "Goodbye, cruel world";
Data[2] = ptr2;

ptr3 = (char **) malloc(10 * sizeof(char *));
Data[4] = ptr3;

ptr3[0] = "Message 0";
ptr3[1] = "Message 1";
 ...
ptr3[9] = "Message 9"; 

printf("%s\n", *Data[0]);
printf("%s\n", Data[2][0]);
printf("%s\n", Data[4][0]);
printf("%s\n", Data[4][1]);
      ...
printf("%s\n", Data[4][9]);

Подумайте об этом так: каждая запись в массивеchar **, Каждая запись может указывать на произвольное местоположение в памяти, причем указанное местоположение (я)char * и, следовательно, возможность указывать на массив символов с нулевым символом в конце, также называемый «строка».

Обратите внимание на разницу между этим и тем, что вы получаете, когда выделяете двумерный массив:

char *Data2[10][70]={NULL};

РаспределениеData2 выше дает вам 2-мерный массивchar * указатели, указанный двумерный массив размещается в одном фрагменте памяти (10 * 70 * sizeof(char*) байтов, или 2800 байтов с 32-битными указателями). У вас нет возможности назначитьchar ** указатели на произвольные места в памяти, которые у вас есть с одномерным массивомchar ** указатели.

Также обратите внимание (приведенные выше декларацииData а такжеData2) что компилятор сгенерирует другой код для следующих ссылок на массив:

Data[0][0]
Data2[0][0]

Here's another way to think about thisПредставьте, что у вас есть несколько массивов указателей на строки:

char *table0[] = { "Tree", "Bench", "Stream" };
char *table1[] = { "Cow", "Dog", "Cat" };
char *table2[] = { "Banana", "Carrot", "Broccoli" };
char **Data[3];

Data[0] = table0;
Data[1] = table1;
Data[2] = table2;

У вас есть массив указателей на «массив указателей на символ». Если вы теперь печатаете значениеdata[1][1]Думайте об этом так:data[1] получает указатель на массивtable1, Тогда значениеtable1[1] равняется"Dog".

Error: User Rate Limit Exceeded T.T.T.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/423823/…Error: User Rate Limit Exceeded

Похожие вопросы