Передача перечислений в функции, которая находится в структуре (в C) - PullRequest
2 голосов
/ 24 июня 2011

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

test_setup.h:

     1 #ifndef TEST_SETUP_H_
     2 #define TEST_SETUP_H_
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 
     6 
     7 typedef struct _test_setup {
     8 
     9   int *partner;            
    10   int *send_first;         
    11   double *results;         
    12 
    13   enum { CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE } SomeMatches;
    14   void match_partners(SomeMatches match);
    15 
    16 } test_setup;              
    17 
    18 #endif

test_setup.c:

     1 #include "../includes/test_setup.h"
     2 
     3 void match_partners(SomeMatches match) { 
     4   if (match == CHIP_WIDE) {
     5 
     6   }
     7   else if (match == NODE_WIDE) {
     8 
     9   }
    10   else if (match == SYSTEM_WIDE) {
    11 
    12   }
    13   else {
    14 
    15   }
    16 }`

Ошибка:

    In file included from src/test_setup.c:1:
    src/../includes/test_setup.h:14: error: expected ‘)’ before ‘match’
    src/../includes/test_setup.h:16: warning: no semicolon at end of struct or union
    src/test_setup.c:3: error: expected ‘)’ before ‘match’
    make: *** [setup.o] Error 1

Я пробовал каждую комбинацию объявления перечисления и использования его в параметрах функции, но ничего не получалось. Любые идеи будут высоко оценены. Я компилирую с mpicc (потому что остальная часть программы использует функции MPI), но я пробовал с GNU GCC, и я получаю те же предупреждения / ошибки.

Ответы [ 4 ]

4 голосов
/ 24 июня 2011

Для C

Если вы действительно хотите C, то вы просто не можете ничего сделать.

  • Вы не можете определить членафункция в структуре
  • Вы не можете определить именованное перечисление, вложенное в структуру

Для C ++

Использовать разрешение областиоператор ::

#include<iostream>

struct Test
{
  enum SomeEnum { TEST1, TEST2, TEST3 };
  void SomeFunction(SomeEnum e);
};

void Test::SomeFunction(Test::SomeEnum e)
{
  std::cout << e << "\n";
}

int main(int argc, char* argv[])
{
  Test t;
  t.SomeFunction(Test::TEST1);
  return 0;
}
2 голосов
/ 24 июня 2011

Если вы хотите сделать это в C, вот обходные пути:

// define the enumeration at file scope:

typedef enum {CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE} SomeMatches;

// declare a *pointer* to a function in the struct:
typedef struct { 
    int *partner;
    int *send_first;
    double *results;

    void (*match_partners)(SomeMatches match);   
} test_setup;

Определите вашу функцию как обычно:

void match_partners(SomeMatches match)
{
  if (match == CHIP_WIDE) {}
  else if (match == NODE_WIDE) {}
  else if (match == SYSTEM_WIDE) {}
}

Затем при создании экземпляра структуры присвойте указатель функции:

test_setup t;
t.match_partners = match_partners;

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

t.match_partners(CHIP_WIDE);

хотя, если вы хотите явно разыменовать его, используйте

(*t.match_partners)(CHIP_WIDE);

Обратите внимание, что C не имеет эквивалента указателю this; если match_partners зависит от информации, содержащейся в экземпляре структуры, вам придется явно передать этот экземпляр в качестве отдельного аргумента:

void match_parthers(SomeMatches matches, test_setup *instance) 
{
}
...
typedef struct {
  ...
  void (*match_partners)(SomeMatches matches, test_setup *instance);
  ...
} test_setup;
...
test_setup t;
t.match_partners = match_partners;
t.match_partners(CHIP_WIDE, &t);

Обратите внимание, что для того, чтобы определение структуры было допустимым, мы должны передать экземпляр как указатель , так как тип test_setup на этом этапе не завершен.

EDIT

Это последнее предложение не очень ясно; Дай мне попробовать снова. Определение структуры не может ссылаться на сам экземпляр, потому что тип структуры не является завершенным до закрытия }. IOW, следующее не законно:

struct foo
{
  ...
  struct foo bar;
  ...
};

Однако структура может ссылаться на указатель на другой экземпляр того же типа, поэтому допустимо следующее:

struct foo
{
  ...
  struct foo *bar;
  ...
};

Та же логика применяется к объявлению указателя функции; параметр instance должен быть объявлен как test_setup *, так как определение типа test_setup на данный момент не завершено. Как отмечает Мерлин в комментариях, вы, вероятно, в любом случае хотите, чтобы экземпляр был изменяемым, но язык требует, чтобы вы использовали указатель в таких обстоятельствах.

0 голосов
/ 24 июня 2011

Прежде всего #define TEST_SETUP_H_ идет до #ifndef TEST_SETUP_H_.В противном случае ваш код будет полностью закомментирован для компилятора.

Вы не можете назвать структуру typedef так, как она выглядит следующим образом: typedef struct struct_name {/ contents /};

void match_partners(SomeMatches match) может быть void match_partners(void) и использовать переменную внутри функции, потому что с этим заголовочным файлом вы сделали его глобальным и не должны передавать его.

0 голосов
/ 24 июня 2011

Ваше перечисление не имеет правильного имени (у него нет тега) и на него нельзя ссылаться из разных точек кода.Попробуйте это:

enum SomeMatches { CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE };
struct _test_setup {
     /* ... */
     enum SomeMatches SomeMatches;
     void (*match_partners)(enum SomeMatches match);
     /* ... */
};

Посыпьте typedefs по желанию или оставьте вещи голыми ...

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