C двойной указатель на структуру - PullRequest
23 голосов
/ 03 октября 2011

Я пытаюсь определить двойной указатель на структуру в C и не могу понять, что происходит ... Простой источник приведен ниже:

typedef struct
{
    int member;
} mystruct;

void myfunc(mystruct **data)
{
    (*data)->member = 1;
}

void main(int argc, char *argv[])
{
    mystruct **data;

    myfunc(data);

    printf("member = %d\n", (*data)->member);
}

Аналогичный вопрос был задан здесь: Как работать с указателем на указатель на структуру в C? о том, как изменить член структуры через двойной указатель. Решением был синтаксис (*data)->member = 1;, который имеет смысл. Но в моем небольшом приложении здесь я получаю ошибку seg при выполнении этой строки. Что я делаю неправильно?

Спасибо

Ответы [ 5 ]

18 голосов
/ 03 октября 2011

Вам нужно указать на что-то, если вы собираетесь разыменовать указатель.Попробуйте это:

void main(int argc, char *argv)
{
    mystruct actualThing;
    mystruct *pointer = &actualThing;
    mystruct **data = &pointer;
    myfunc(data);

    printf("Member: %d", (*data)->member);
}
7 голосов
/ 03 октября 2011

Вы получили segfault, потому что не указали структуру.

Значение data является мусором, поэтому оно указывает на какое-то место в памяти, которое не принадлежит вашему процессу или является иным образомнедоступен.

Сначала необходимо выделить объект типа mystruct.Вот рабочий пример для вас: http://ideone.com/XIdJ8

5 голосов
/ 03 октября 2011

data не инициализируется и, следовательно, не указывает на какой-либо разумный адрес памяти.Более того, нет никакой структуры mystruct, поэтому на самом деле нет никаких разумных данных, на которые можно было бы указать.Например, вы хотите:

  1. Создать mystruct.
  2. Сделать указатель на него.
  3. Сделать указатель на этот указатель.
1 голос
/ 04 октября 2011

Если вам нужно только передать двойной указатель на библиотечную функцию, вам не нужно создавать переменную для нее. Вы создаете обычную переменную-указатель, инициализируете ее, чтобы она указала на соответствующее хранилище (если это требуется функцией), затем передаете адрес указателя (таким образом, создавая двойной указатель «на лету»).

Я никогда не использовал libusb, поэтому приведу пример использования стандартной библиотечной функции. С справочной страницы:

   #include <stdlib.h>

   long int strtol(const char *nptr, char **endptr, int base);

Это только выглядит как двойной указатель. Это действительно одиночный указатель с имитацией передачи по ссылке. Разрешение функции возвращать дополнительную информацию помимо ее обычного возвращаемого значения. strtol возвращает длинное целое число, но оно также может сказать вам, в какой момент содержимое строки перестало выглядеть как число.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char *str = "99RED BALLOONS";
    char *what;
    long num;

    num = strtol(str, &what, 10);
    printf("Quantity: %ld;    Description: %s;\n", num, what);

    return 0;
}

Выход:

Quantity: 99;    Description: RED BALLOONS;
0 голосов
/ 03 октября 2011

Вы передаете ему указатель, но указатель ни на что не указывает.

Это может быть более полезно:

void main(int argc, char *argv[])
{
    mystruct data;
    mystruct *ptr = &data;
    myfunc(&ptr);
    printf("member = %d\n", (*ptr)->member);
}
...