Как правильно определить указатель на функцию в структуре, которая принимает структуру в качестве указателя? - PullRequest
8 голосов
/ 01 октября 2010

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

typedef struct {

    // some fields required for processing...

    int (*doAction)(struct pr_PendingResponseItem *pr);
} pr_PendingResponseItem;

Если я удаляю атрибут «struct» в параметре pr, я получаю сообщение об ошибке.Если я оставлю это, я получу предупреждение: «его область действия - только это определение или объявление, что, вероятно, не то, что вы хотите»

Все это работает, но я хотел бы знать, как правильно определитьтакая структура.

Также связано определение собственной ссылочной структуры:

typedef struct LinkedItem_ {
    LinkedItem_ * prev;
    LinkedItem_ * next;
    void * data;
} LinkedItem;

(Я думаю, что это правильно, но дополнительные мысли приветствуются, если это связано с вопросом.)

Ответы [ 4 ]

12 голосов
/ 01 октября 2010

Ваш указатель на функцию ссылается на struct pr_PendingResponseItem, но вы не объявили struct pr_PendingResponseItem.У вас просто есть безымянная структура typedef с именем pr_PendingResponseItem (и это имя еще не установлено).

Дайте структуре имя:

struct pr_PendingResponseItem {

    // some fields required for processing...

    int (*doAction)(struct pr_PendingResponseItem *pr);
} ;
typedef struct pr_PendingResponseItem pr_PendingResponseItem;
8 голосов
/ 01 октября 2010

Есть два способа сделать это - для обоих ваших примеров структур.Они в основном изоморфны.

  1. Используйте тег структуры, как уже показано в различных других ответах.

    typedef struct pr_PendingResponseItem
    {
        // some fields required for processing...
        int (*doAction)(struct pr_PendingResponseItem *pr);
    } pr_PendingResponseItem;
    
    typedef struct LinkedItem
    {
        struct LinkedItem *prev;
        struct LinkedItem *next;
        void * data;
    } LinkedItem;
    
  2. Используйте typedef длядать имя неполному типу структуры и использовать typedef в определении структуры.

    typedef struct pr_PendingResponseItem pr_PendingResponseItem;
    struct pr_PendingResponseItem
    {
        // some fields required for processing...
        int (*doAction)(pr_PendingResponseItem *pr);
    };
    
    typedef struct LinkedItem LinkedItem;
    struct LinkedItem
    {
        LinkedItem *prev;
        LinkedItem *next;
        void * data;
    };
    

Обратите внимание, что теги структуры находятся в другом пространстве имен, чем имена typedef, поэтому нет необходимости использовать разные имена для тега typedef и структуры.Также обратите внимание, что в C ++ typedef будет ненужным.

3 голосов
/ 01 октября 2010

что-то вроде этого

typedef struct _pr_PendingResponseItem_ {

    // some fields required for processing...

    int (*doAction)(struct _pr_PendingResponseItem_ *pr);
} pr_PendingResponseItem;

должно это исправить.

(проверено и работает)

0 голосов
/ 01 октября 2010

Добавление к ответу номерами выше.

Ключевым моментом здесь является то, что при работе с объявлением типа "typedef struct name1 {} name2;" вы фактически объявляете два типа, т.е. " struct name1 {};" а затем "typedef struct name1 name2 ;", где " struct name1 " является типом, и вы должны использовать синтаксис "struct name1" для ссылки на него, и " name2"- это тип, и вы называете его" name2 ". Вам разрешено не указывать name1, в этом случае вы просто определяете второй тип, а первый остается анонимной структурой.

Теперь, в первом случае, если вы хотите сослаться на тип "struct pr_PendingResponseItem", вам нужно объявить этот тип вместо анонимной структуры, которую вы объявили. Итак, измените объявление структуры на «struct pr_PendingResponseItem».

Во втором случае вы пытаетесь ссылаться на тип структуры как прямую ссылку (то есть ссылаться на него до завершения определения), что разрешено, но для ссылки на тип структуры требуется синтаксис " имя структуры ". Поэтому вам нужно заменить прямые ссылки на «LinkedItem_» в вашем определении на «struct LinkedItem _».

...