typedef структур, которые не проходят в файлах заголовков?

У меня возникли проблемы с некоторыми объявлениями struct typedef в файле заголовка, которые, похоже, не проходят в мой файл реализации.

В частности, у меня определены следующие типы: Type, Value, Integer, String и Float. Все они определяются по именам структур одинаковым образом. Я пишу неофициальную hashCode функцию для дополнения разрабатываемой мной хэш-таблицы, которая ссылается на все эти типы данных. Тип и значение работают нормально, но Integer / Float / String не работают должным образом, и я не могу понять, почему.

Прошу прощения, этот вопрос немного сложен, но я постараюсь не предоставлять слишком много или слишком мало информации, и, возможно, это не будет слишком сложно для экспертов здесь. :-)

Я начну с функции hashCode (и, пожалуйста, не расстраивайтесь, насколько это дерьмо, я знаю, что это не так уж и здорово, и мне действительно все равно):

int hashCode(ST_HashSymbol *hash, Value *v)
{
        Type *t = v->type;

        switch (whichType(t->name))
        {
                case INTEGER:
                        Integer *i = (Integer *)v->innerValue;
                        return i->value % hash->capacity;

        case FLOAT:
        {
            Float *f = (Float *)v->innerValue;
            float val = f->value;
            long l = 0l;

            if (val  2 && j = 0; --j)
            {
                if (val >= pow(2, j - 22))
                {
                    val -= pow(2, j - 22);
                    l |= 1 capacity;
        }

                case STRING:
                        String *s = (String *)v->innerValue;
                        char *str = s->value;

                        int total = 0;

                        char *c;
                        for (c = str; *c != '\0'; ++c)
                        {
                                total += *c;
                        }

                        return total % hash->capacity;

                default:
                        return -1;
        }
}

Выдержка из заголовочного файла "type.h", в котором определены все типы. Стоит отметить, что я также пробовал объединить определение типа и определение структуры в один оператор, но это тоже не сработало:

typedef struct _t Type;
typedef struct _v Value;

struct _t {
        char *name;
        struct _t *widerType;
};

struct _v {
        Type *type;
        void *innerValue;
};

Type *type(int);
int whichType(char *);
Type *getType(char *);

/**************************/
/* Actual ("inner") types */
/**************************/

typedef struct _str String;
typedef struct _int Integer;
typedef struct _fl Float;

struct _str {
        int length;
        char *value;
};

struct _int {
        int value;
};
struct _fl {
        float value;
};

Когда я запускаю make, я получаю следующее:

[kparting@dhcp-10-25-247-130 eq]$ make
gcc -o eq -Wall -g parser.c eq.c error.c hash.c symbols.c type.c -lm
hash.c: In function ‘hashCode’:
hash.c:33: error: expected expression before ‘Integer’
hash.c:34: error: ‘i’ undeclared (first use in this function)
hash.c:34: error: (Each undeclared identifier is reported only once
hash.c:34: error: for each function it appears in.)
hash.c:37: error: expected expression before ‘Float’
hash.c:38: error: ‘f’ undeclared (first use in this function)
hash.c:69: error: expected expression before ‘String’
hash.c:70: error: ‘s’ undeclared (first use in this function)
make: *** [eq] Error 1

Как я уже упоминал, Type * и Value * являются допустимыми типами данных, а остальные три - нет. Функции whichType и type не используют ни один из трех других типов данных.

Заранее благодарю за любую помощь. Я почти уверен, что это связано либо с расположением структур в файле заголовка, либо, возможно (но крайне маловероятно) с самим gcc.


person Platinum Azure    schedule 09.10.2009    source источник
comment
Не ответ на ваш вопрос, но я почти уверен, что вы захотите вставить «перерыв» в конце блоков case.   -  person theycallmemorty    schedule 09.10.2009
comment
У вас #included заголовок, верно?   -  person Nick Bedford    schedule 09.10.2009
comment
theycallmemorty: Похоже, он заканчивает каждую с return, поэтому break не требуется.   -  person caf    schedule 09.10.2009
comment
Дело FLOAT было неправильно скопировано, извините. Я копирую из окна оболочки, а не из текстового редактора графического интерфейса, как должен. -_- Не хватает нескольких строк. @ Ник Бедфорд: Да, это слишком элементарная ошибка даже для меня.   -  person Platinum Azure    schedule 09.10.2009
comment
Во всяком случае, я уже принял ответ, но исправил код вопроса ради потомства. :-) Спасибо всем за вашу помощь.   -  person Platinum Azure    schedule 09.10.2009
comment
Быстрый совет: вам не следует использовать typedef, если единственная причина - лениво избегать написания структуры при использовании.   -  person Rerito    schedule 29.01.2013


Ответы (2)


В C вы можете объявлять переменную только в начале блока. Ваша линия:

Integer *i = (Integer *)v->innerValue;

пытается объявить переменную i, но это не в начале блока. Вы можете исправить это, просто открыв блок:

case INTEGER:
{
    Integer *i = (Integer *)v->innerValue;
    return i->value % hash->capacity;
}

... и то же самое для других cases.

person caf    schedule 09.10.2009
comment
Действительно? У меня никогда раньше не было проблем с этим ... Рассмотрим цикл for в части case STRING - это объявление также не находится в начале блока. Но я обязательно попробую и посмотрю, что получится. - person Platinum Azure; 09.10.2009
comment
Хорошо, я буду. Вот и все. Спасибо большое. +1 и отметьте вам галочку. - person Platinum Azure; 09.10.2009
comment
Вы говорите о C89 - в C99 вы можете определять переменные в любом месте блока кода, как и в C ++. - person Jonathan Leffler; 09.10.2009

Вы не можете объявить переменную внутри блока case.

На самом деле это не полностью верно. См. здесь. Должно помочь вам прояснить ситуацию.

person theycallmemorty    schedule 09.10.2009
comment
Очень информативно. Я никогда этого не знал - это так странно. Я действительно хотел бы, чтобы gcc прояснил этот момент, но я давно узнал, что gcc никогда не бывает подробным, даже если он всегда правильный. Спасибо за ответ. - person Platinum Azure; 09.10.2009
comment
В этом нет ничего странного, если вы думаете о case как о том, чем он является на самом деле. Это не блок, это просто метка, для которой switch вычисляется goto. Вот почему case может быть расположен внутри цикла while, например, до тех пор, пока этот while цикл находится внутри switch (и, следовательно, мы добираемся до устройства Даффа). - person Pavel Minaev; 09.10.2009