Доступ к переменным в структурах C

I am not too familiar with C programming, and I have to do few modifications on a source code, here is the problem:
I have this in a header file :

typedef struct word {
  long    wnum;
  float   weight;
} WORD;

typedef struct svector { WORD *words; двойная норма; } СВЕКТОР;

В моем файле file.c у меня есть такая функция, как

double function(SVECTOR *a, SVECTOR *b){

}

что я должен сделать, чтобы в моей функции получить доступ к переменным wnum и weight???
Заранее спасибо ;)


person jamel    schedule 16.11.2009    source источник
comment
На заметку: не называйте структуру WORD. Это обычный #define для unsigned short. Давным-давно два байта назывались СЛОВАМИ. Это обычное определение в коде библиотеки, особенно в коде Windows.   -  person jmucchiello    schedule 16.11.2009


Ответы (6)


Вы проходите мимо:

a->words->wnum
a->words->weight

Or:

a->words[SUBINDEX].wnum
a->words[SUBINDEX].weight

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

  1. Если вы получаете указатель на один элемент SVECTOR, вы можете использовать первый подход.
  2. С другой стороны, если вы получаете указатель на серверные элементы SVECTOR, второй подход может показаться вам более удобным.
person Pablo Santa Cruz    schedule 16.11.2009

Обязательно проверьте наличие нулевых указателей, но в целом это будет:

a->words->wnum
a->words->weight

Поскольку это называется словами, это звучит так, как будто это может быть массив (проверьте код, чтобы быть уверенным). Вам, вероятно, потребуется перебрать массив. Если вы можете показать больше кода или указать на какую-либо документацию, мы могли бы выяснить, какого размера этот массив.

for( unsigned int t = 0; t < [SIZE OF words ARRAY]; ++t )
{
   a->words[t].wnum;
   a->words[t].weight;
}
person Jesse Vogt    schedule 16.11.2009
comment
и a, и слова могут быть указателями на массив, чего нельзя сказать по коду, который мы видели. - person djna; 16.11.2009
comment
Абсолютно, я думаю, что это массив ... но я не получил ваш цикл for ?? - person jamel; 16.11.2009
comment
Добавлены некоторые комментарии и явно проверено w против 0 (NULL) - person Jesse Vogt; 16.11.2009
comment
Ммм - ваш цикл работал бы, если бы слова были СЛОВОМ **. Поскольку это ваша воля, будет продолжаться, пока вы не segfault. a-›words указывает на кусок памяти, достаточно большой для хранения одной или нескольких структур WORD. ++w увеличивает w на sizeof(WORD). Как w когда-либо будет 0? - person sdtom; 16.11.2009
comment
@sdtom. Хорошая точка зрения. Собираюсь удалить этот код на данный момент. @jamel Можете ли вы показать, как распределяются слова? - person Jesse Vogt; 16.11.2009
comment
Все равно не совсем правильно. Вам нужны a-›words[t].wnum и a-›words[t].weight. На самом деле нет никакого способа, чтобы массив завершался нулем (кроме сохранения какого-то сторожевого значения в самой последней структуре WORD, т.е. сохранения какого-то специального значения в wnum или веса, которые указывали на конец массива). - person sdtom; 17.11.2009

a->words->wnum

-> одновременно разыменовывает указатель и позволяет ссылаться на поле структуры.

person Heinzi    schedule 16.11.2009

Судя по именам SVECTOR и словам, похоже, что вы имеете дело с массивами. Вот несколько вариантов:

/**
 * a and words are meant to be treated as arrays
 */
a[i].words[j].wnum = ...;
a[i].words[j].weight = ...;
/**
 * a is treated as an array, words is not
 */
a[i].words->wnum = ...;
a[i].words->weight = ...;
/**
 * a is not treated as an array, words is
 */
a->words[j].wnum = ...;
a->words[j].weight = ...;
/**
 * a and words are not treated as arrays
 */
a->words->wnum = ...;
a->words->weight = ...;

Так зачем использовать ., когда мы применяем индекс, и ->, когда мы этого не делаем? Прежде всего, помните, что вы используете -> при доступе к членам структуры через указатель и . при доступе к членам через экземпляр структуры. Операция индекса массива определяется как a[i] == *(a + i); акт подписки эффективно разыменовывает указатель. Таким образом, тип words — это struct word * (указатель на структурное слово), а тип words[i] — это struct word. Поэтому нам нужно использовать -> для первого и . для второго. Те же рассуждения справедливы для a и b.

ЕСЛИ a, b или words предназначены для обработки как массивы, их размер должен быть где-то известен.

person John Bode    schedule 16.11.2009
comment
Я думаю, что слова - это массив. Знаете ли вы способ получить его размер, чтобы я мог перебрать его? - person jamel; 16.11.2009
comment
Судя по коду, который вы опубликовали, нет. Указатель words не несет никакой информации о размере блока, на который он указывает. Учитывая то, что вы опубликовали, вероятно, существует глобальная переменная или определение макроса, в котором хранится эта информация, но лучше спросить кого-то, кто знает, как должен работать этот код. - person John Bode; 16.11.2009

Редактировать: (добавлено words, я пропустил тот факт, что было две вложенные структуры, в спешке объяснить различные операторы отсылки...)
т. е. первоначальный ответ был похож на some_long_var = a->wNum;, который конечно неправильно...

2 попытка ;-)

some_long_var = a->words->wNum;
//  or
some_float_var = a->words->weight;

должно помочь.

Поскольку a и b являются указателями, их необходимо сначала разыменовать, прежде чем можно будет получить доступ к их членам. Оператор -> делает обе вещи одновременно.

В качестве альтернативы вы можете сделать что-то вроде

some_long_var = a[0].words->wNum;

(или, возможно, со значением, отличным от 0, в качестве нижнего индекса, если вы ожидаете, что a будет массивом). Дело в том, что в C массивы часто "рассматриваются" как указатели на тип элемента, найденного в массиве, и поэтому оператор массива [] может быть функционально и часто семантически правильным способом разыменование указателя.

Наконец, но это более надуманный (но полезный для понимания семантики различных операторов c), вы можете сделать это в два этапа, при этом оператор * выполняет разыменование, а оператор-член (.) получает желаемую структуру /член класса:

some_long_var = (*a).words->wNum;
person mjv    schedule 16.11.2009
comment
Вообще-то, нет. Переменная a является указателем на SVECTOR, а не на WORD. Как показывает Хайнци, вам нужно косвенно использовать его поле words. - person Andy Ross; 16.11.2009

У вас есть указатель на определенный тип WORD, поэтому:

a->words->(member)

Если у вас просто был член, не являющийся указателем, вы должны сделать:

a->words.(member) 
person jonaspp    schedule 16.11.2009