Почему мы использовали двойной и тройной указатель в языке target-C или C? - PullRequest
2 голосов
/ 03 апреля 2010

Я запутался, когда я хочу взять один указатель и когда мне взять двойной указатель? В следующей структуре, что именно делал?

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

Почему мы используем двойной указатель "** methodLists".

Отредактировано int sqlite3_get_table ( sqlite3 * db,
const char * zSql,
char *** pazResult,
int * pnRow,
int * pnColumn,
char ** pzErrmsg
); В приведенном выше сценарии, что будет означать тройной указатель char *** pazResult?

Ответы [ 4 ]

6 голосов
/ 03 апреля 2010

Ну, по крайней мере в C, двойные указатели обычно используются для 2D-массивов. Наиболее распространенный 2D-массив - это, вероятно, массив строк C (char*). Двойные указатели также иногда используются для передачи указателей на функции по ссылке , но это вряд ли будет использоваться в примере кода, который вы опубликовали.

По названию methodLists Я бы предположил, что это массив списков. Связанный список в C обычно представлен указателем на узел, которым может быть objc_method_list. Затем массив таких списков реализуется с двойным указателем.

4 голосов
/ 12 апреля 2010

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

Например, если вы пытались переписать функцию strcpy, чтобы пользователю не приходилось выделять память для исходной строки, вы можете попробовать что-то вроде следующего:

void MyStrcpy(char* dst, char* src){ 
  dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
  for(int i=0;i<=strlen(src);i++)
    dst[i] = src[i];
  printf("src: %s ", src);
  printf("dst: %s\n\n", dst);
}

Если бы вы тогда вызывали эту функцию,

int main() {
     char *foo = "foo";
     char *newPtr;

     MyStrcpy(newPtr, foo);

     printf("foo: %s ", foo);
     printf("new: %s\n", newPtr);
}

Ваш вывод будет следующим:

источник: foo dst: foo

foo: foo новый:

Вы также можете получить ошибку сегмента при попытке печати newPtr, в зависимости от вашей системы. Причина такого поведения точно такая же, как и причина, по которой вы не ожидаете, что изменение int, переданное по значению в функцию, будет отражено вне этой функции: то, что вы передаете MyStrcpy, это просто адрес памяти, ссылки на newPtr. Когда вы выделяете пространство для dst внутри функции, вы меняете адрес, на который указывает dst. Это изменение не будет отражено за пределами MyStrcpy!

Вместо этого, если вы хотите, чтобы newPtr указывал на новый выделенный фрагмент памяти, вы должны иметь указатель dst на указатель, символ **.

void MyStrcpy(char** dst, char* src){ 
  *dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
  for(int i=0;i<=strlen(src);i++)
    (*dst)[i] = src[i];
  printf("src: %s ", src);
  printf("dst: %s\n\n", *dst);
}

Теперь, если бы вы вызвали эту функцию:

int main() {
  char *foo = "foo";
  char *newPtr;

  MyStrcpy(&newPtr, foo);

  printf("foo: %s ", foo);
  printf("new: %s\n", newPtr);
}

Вы получите ожидаемый результат:

src: foo dst: foo

foo: foo new: foo

Надеюсь, это поможет!

3 голосов
/ 03 апреля 2010
2 голосов
/ 03 апреля 2010

В самом общем случае двойной указатель - это указатель на список указателей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...