В C, что означает объявление переменной с двумя звездочками (**)?
Я работаю с C, и я немного ржавый. Я знаю, что *
имеет три вида использования:
- Объявление указателя.
- Вызов указателя.
- Умножение
Однако, что это означает, когда перед объявлением переменной есть две звездочки (**
):
char **aPointer = ...
Спасибо,
Скотт
Ответы
Ответ 1
Он объявляет указатель указателю char
.
Использование такого указателя будет заключаться в том, чтобы делать такие вещи, как:
void setCharPointerToX(char ** character) {
*character = "x"; //using the dereference operator (*) to get the value that character points to (in this case a char pointer
}
char *y;
setCharPointerToX(&y); //using the address-of (&) operator here
printf("%s", y); //x
Вот еще один пример:
char *original = "awesomeness";
char **pointer_to_original = &original;
(*pointer_to_original) = "is awesome";
printf("%s", original); //is awesome
Использование **
с массивами:
char** array = malloc(sizeof(*array) * 2); //2 elements
(*array) = "Hey"; //equivalent to array[0]
*(array + 1) = "There"; //array[1]
printf("%s", array[1]); //outputs There
Оператор []
на массивах делает по существу указательную арифметику на указателе спереди, поэтому способ array[1]
будет оцениваться следующим образом:
array[1] == *(array + 1);
Это одна из причин, по которой индексы массива начинаются с 0
, потому что:
array[0] == *(array + 0) == *(array);
Ответ 2
C и С++ позволяют использовать указатели, указывающие на указатели (скажем, пять раз быстрее). Взгляните на следующий код:
char a;
char *b;
char **c;
a = 'Z';
b = &a; // read as "address of a"
c = &b; // read as "address of b"
Переменная a
содержит символ. Переменная b
указывает на место в памяти, которое содержит символ. Переменная c
указывает на место в памяти, которое содержит указатель, указывающий на место в памяти, содержащее символ.
Предположим, что переменная a
хранит свои данные по адресу 1000 (BEWARE: примеры расположения памяти полностью заполнены). Предположим, что переменная b
хранит свои данные по адресу 2000 и что переменная c
хранит свои данные по адресу 3000. Учитывая все это, мы имеем следующий макет памяти:
MEMORY LOCATION 1000 (variable a): 'Z'
MEMORY LOCATION 2000 (variable b): 1000 <--- points to memory location 1000
MEMORY LOCATION 3000 (variable c): 2000 <--- points to memory location 2000
Ответ 3
Это означает, что aPointer
указывает на указатель char.
Итак,
aPointer: pointer to char pointer
*aPointer :pointer to char
**aPointer: char
Примером его использования является создание динамического массива строк c
char **aPointer = (char**) malloc(num_strings);
aPointer дает вам char, который может использоваться для представления строки с нулевым завершением.
*aPointer = (char*)malloc( string_len + 1); //aPointer[0]
*(aPointer + 1) = (char*)malloc( string_len + 1); //aPointer[1]
Ответ 4
Он объявляет aPointer
как указатель на указатель на char.
Объявления в C сосредоточены вокруг типов выражений; общее название для него - "использование имитаций объявления". В качестве простого примера предположим, что у нас есть указатель на int с именем p
, и мы хотим получить доступ к целочисленному значению, которое оно указывает в настоящее время. Мы бы разыменовали указатель с унарным оператором *
, например:
x = *p;
Тип выражения *p
равен int
, поэтому объявление переменной-указателя p
равно
int *p;
В этом случае aPointer
является указателем на указатель на char; если мы хотим получить значение символа, на которое он указывает сейчас, нам придется разыгрывать его дважды:
c = **aPointer;
Итак, переходя по логике выше, объявление переменной-указателя aPointer
равно
char **aPointer;
поскольку тип выражения **aPointer
равен char
.
Почему у вас всегда есть указатель на указатель? Он отображается в нескольких контекстах:
- Вы хотите, чтобы функция изменяла значение указателя; одним из примеров является библиотечная функция
strtol
, прототипом которой (с C99) является
long strtol(const char * restrict str, char ** restrict ptr, int base);
Второй аргумент - указатель на указатель на char; когда вы вызываете strtol
, вы передаете адрес указателя на char в качестве второго аргумента, а после вызова он указывает на первый символ в строке, которая не была преобразована.
- Помните, что в большинстве контекстов выражение типа "N-element array of T" неявно преобразуется в тип "указатель на T", а его значение является адресом первого элемента массива. Если "T" является "указателем на char", выражение типа "N-элементный массив указателя на char" будет преобразовано в "указатель на указатель на char". Например:
void foo(char **arr)
{
size_t i = 0;
for (i = 0; arr[i] != NULL; i++)
printf("%s\n", arr[i]);
}
void bar(void)
{
char *ptrs[N] = {"foo", "bar", "bletch", NULL};
foo(ptrs); // ptrs decays from char *[N] to char **
}
- Вы хотите динамически выделять многомерный массив:
#define ROWS ...
#define COLS ...
...
char **arr = malloc(sizeof *arr * ROWS);
if (arr)
{
size_t i;
for (i = 0; i < ROWS; i++)
{
arr[i] = malloc(sizeof *arr[i] * COLS);
if (arr[i])
{
size_t j;
for (j = 0; j < COLS; j++)
{
arr[i][j] = ...;
}
}
}
}
Ответ 5
Это указатель на указатель на char
.