«Разыменование» указателя означает доступ к значению, на которое указывает указатель.Предположим следующие объявления:
int a = 10;
int *p = &a;
Вот гипотетическая карта памяти двух переменных:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
a 0x80001000 0x00 0x00 0x00 0x0A
p 0x80001004 0x80 0x00 0x10 0x00
a
содержит целочисленное значение 10. p
содержит адрес a
(0x80001000).Если мы хотим получить доступ к содержимому от a
до p
, мы разыменовываем p
с помощью оператора косвенности *
.Таким образом, выражение *p
эквивалентно выражению a
.Если мы написали
*p = 16;
, это то же самое, что написать
a = 16;
Вот небольшой фрагмент кода, показывающий, как использовать объект типа char **
для создания массива строк:
#include <stdlib.h>
#define N 20 // For this example, we will allocate 20 strings
#define LENGTH 10 // of 10 characters each (not counting 0 terminator)
...
char **arr = malloc(sizeof *arr * N);
if (arr)
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
strcpy(arr[i], " ");
}
}
Проходя по этой строке построчно,
char **arr = malloc(sizeof *arr * N);
выделяет блок из N элементов, каждый из которых достаточно большой для хранения указателя на символ (sizeof *arr
== sizeof (char *)
начиная с типа *arr
== char *
), и присваивает результирующее значение указателя arr
.IOW, arr
указывает на первый указатель на char
, следовательно, тип char **
.Обратите внимание, что если вы разделите объявление и вызов функции, это будет выглядеть как
char **arr;
...
arr = malloc(sizeof *arr * N);
Мы хотим присвоить результат malloc
для arr
, а не для того, что arr
очковдо .
if (arr)
Может произойти сбой malloc
, поэтому мы хотим проверить результат перед его использованием.В случае сбоя malloc
возвращается значение указателя NULL.
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
Для каждого символьного указателя arr[i]
мы выделяем блок памяти, достаточно большой для элементов LENGTH + 1, каждый из которых достаточно большой, чтобы содержать значение char
(sizeof *arr[i] == sizeof (char)
, поскольку тип *arr[i] == char
; обратите внимание, что sizeof (char)
всегда 1) и присвойте результат arr[i]
.
Поскольку мы выделяем каждую строку отдельным вызовом malloc
, маловероятно, чтобы они были смежными в памяти.Вот еще одна карта памяти, показывающая возможный результат кода выше:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
arr 0x80001000 0xA0 0xCC 0x00 0x00
...
arr[0] 0xA0CC0000 0xA0 0xCC 0x20 0x00
arr[1] 0xA0CC0004 0xA0 0xCC 0x20 0x40
arr[2] 0xA0CC0008 0xA0 0xCC 0x21 0x28
...
arr[19] 0xA0CC0014 0xA0 0xCC 0x23 0x10
...
arr[0][0] 0xA0CC2000 ' ' ' ' ' ' ' '
arr[0][4] 0xA0CC2004 ' ' ' ' ' ' ' '
arr[0][8] 0xA0CC2008 ' ' ' ' 0x00 0x??
...
arr[1][0] 0xA0CC2040 ' ' ' ' ' ' ' '
arr[1][4] 0xA0CC2044 ' ' ' ' ' ' ' '
arr[1][8] 0xA0CC2048 ' ' ' ' 0x00 0x??
...