Это указатель на указатель, как в C (на котором, несмотря на странный синтаксис в квадратных скобках, Objective-C основан):
char c;
char *pc = &c;
char **ppc = &pc;
char ***pppc = &ppc;
и т. Д. До бесконечности (или до тех пор, пока не закончится переменное пространство).
Он часто используется для передачи указателя на функцию, которая должна иметь возможность изменять сам указатель (например, перераспределение памяти для объекта переменного размера).
=====
Следуя вашему запросу на образец, который показывает, как его использовать, вот код, который я написал для другого поста, который иллюстрирует это. Это appendStr()
функция, которая управляет своими собственными выделениями (вам все еще нужно освободить финальную версию). Первоначально вы устанавливаете строку (char *
) в NULL, и сама функция будет выделять пространство по мере необходимости.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendToStr (int *sz, char **str, char *app) {
char *newstr;
int reqsz;
/* If no string yet, create it with a bit of space. */
if (*str == NULL) {
*sz = strlen (app) + 10;
if ((*str = malloc (*sz)) == NULL) {
*sz = 0;
return;
}
strcpy (*str, app);
return;
}
/* If not enough room in string, expand it. We could use realloc
but I've kept it as malloc/cpy/free to ensure the address
changes (for the program output). */
reqsz = strlen (*str) + strlen (app) + 1;
if (reqsz > *sz) {
*sz = reqsz + 10;
if ((newstr = malloc (*sz)) == NULL) {
free (*str);
*str = NULL;
*sz = 0;
return;
}
strcpy (newstr, *str);
free (*str);
*str = newstr;
}
/* Append the desired string to the (now) long-enough buffer. */
strcat (*str, app);
}
static void dump(int sz, char *x) {
if (x == NULL)
printf ("%8p [%2d] %3d [%s]\n", x, sz, 0, "");
else
printf ("%8p [%2d] %3d [%s]\n", x, sz, strlen (x), x);
}
static char *arr[] = {"Hello.", " My", " name", " is", " Pax",
" and"," I", " am", " old."};
int main (void) {
int i;
char *x = NULL;
int sz = 0;
printf (" Pointer Size Len Value\n");
printf (" ------- ---- --- -----\n");
dump (sz, x);
for (i = 0; i < sizeof (arr) / sizeof (arr[0]); i++) {
appendToStr (&sz, &x, arr[i]);
dump (sz, x);
}
}
Код выводит следующее. Вы можете увидеть, как меняется указатель, когда в текущей выделенной памяти заканчивается свободное место для расширенной строки (в комментариях):
Pointer Size Len Value
------- ---- --- -----
# NULL pointer here since we've not yet put anything in.
0x0 [ 0] 0 []
# The first time we put in something, we allocate space (+10 chars).
0x6701b8 [16] 6 [Hello.]
0x6701b8 [16] 9 [Hello. My]
0x6701b8 [16] 14 [Hello. My name]
# Adding " is" takes length to 17 so we need more space.
0x6701d0 [28] 17 [Hello. My name is]
0x6701d0 [28] 21 [Hello. My name is Pax]
0x6701d0 [28] 25 [Hello. My name is Pax and]
0x6701d0 [28] 27 [Hello. My name is Pax and I]
# Ditto for adding " am".
0x6701f0 [41] 30 [Hello. My name is Pax and I am]
0x6701f0 [41] 35 [Hello. My name is Pax and I am old.]
В этом случае вы передаете **str
, так как вам нужно иметь возможность изменить значение *str
.
=====
Или следующее, которое выполняет развернутую пузырьковую сортировку (о, позор!) Для строк, которых нет в массиве. Это происходит путем прямого обмена адресами строк.
#include <stdio.h>
static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) {
char *t;
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s4, *s5) > 0) { t = *s4; *s4 = *s5; *s5 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
}
int main (int argCount, char *argVar[]) {
char *a = "77";
char *b = "55";
char *c = "99";
char *d = "88";
char *e = "66";
printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
sort (&a,&b,&c,&d,&e);
printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
return 0;
}
, который производит:
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не берите в голову реализацию сортировки, просто обратите внимание, что переменные передаются как char **
, чтобы их можно было легко поменять местами. Любая реальная сортировка, вероятно, будет действовать на истинный массив данных, а не на отдельные переменные, но дело не в этом.