#c
#c
Вопрос:
Я объявляю новую структуру с именем «Struct», у меня есть универсальная функция, которая принимает в качестве аргумента «void *data».
void Foo(void *data)
Я передаю экземпляр «Struct» в универсальную функцию.
Struct s;
Foo(amp;s);
Я хочу получить доступ к одному из свойств структуры в функции.
void Foo(void *data) {
char *word = (char*) data.word;
}
Это недопустимо, поскольку оно не распознает данные как допустимую структуру.
Я даже пытаюсь сначала объявить данные как тип struct, и я получаю ошибку.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
Я получаю «запрошено преобразование в нескалярный тип».
Комментарии:
1. Если вам нужно, чтобы это была структура, зачем вообще передавать void*?!
2. @Bo: Функция может быть функцией обратного вызова, которая должна соответствовать внешне определяемому API, вызывающий объект и функция будут знать, что должно быть в
void *data
но промежуточный код может и не знать. Смотритеbsearch
иqsort
примеры из стандартной библиотеки.
Ответ №1:
Прежде всего, вы должны включить предупреждающие флаги вашего компилятора (все из них). Затем вы должны передать указатель на свой Struct
и использовать что-то другое, чем struct
, в качестве имени переменной:
Struct s;
Foo(amp;s);
Затем в Foo
:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
Вы не можете преобразовать типы без указателей в и из void*
, как вы пытаетесь, преобразование типов указателей в и из void*
, с другой стороны, допустимо.
Комментарии:
1. все из них? Это немного чересчур … например, в gcc опция
-Wwrite-strings
делает gcc компилятором для языка, похожего на, но не совсем,C
🙂2. @pmg: Все из них (и
-Werror
тоже!), пока вы не сможете четко объяснить, какие из них можно удалить и почему 🙂 Когда вы сможете перехватить этот предупреждающий переключатель из hand Grasshopper, вы будете готовы.3. Я только что подсчитал
-W
параметры в моем самом требовательном псевдониме gcc: 58 из них (возможно, я допустил одну или две ошибки в подсчете) … включая,-Werror
но не-Wwrite-strings
😀
Ответ №2:
Вам нужно передать указатель на свою структуру и получить указатель на структуру внутри функции:
Struct struct;
Foo(amp;struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
Комментарии:
1. Кроме того, используйте
struct Struct struct
.2. Приведение к
(Struct*)
не требуется. Некоторым людям нравится включать ее, но я считаю, что лучше этого не делать, потому что это предотвращает предупреждение компилятора, если вы попытаетесь присвоить локальной переменной указатель, не содержащий void.3. О, и еще:
struct
это зарезервированное слово — выберите другое имя для локальной переменной. @Radek: Нет, еслиStruct
это имя typedef.
Ответ №3:
Вы должны использовать ->
оператор при запросе элемента структуры через указатель.
Это должно сработать: char *word = (char*) data->word;
Вы также должны передать адрес структуры функции. Вот так: Foo(amp;struct);
.
Ответ №4:
Во-первых, вам нужно правильно вызвать функцию:
Struct s;
Foo(amp;s);
Обратите внимание, что теперь вы передаете указатель на структуру.
Теперь функция должна знать, что вы используете Struct
(в отличие от чего-то другого) — возможно, из-за другого параметра, или глобальной переменной, или по какой-то другой причине. Затем внутри функции вы можете сделать:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Ответ №5:
Данные — это указатель, поэтому все, к чему вы их приводите, также должно быть указателем. Если бы вы сказали Struct* myStruct = (Struct*) data
, все было бы хорошо в мире.
Ответ №6:
Вы смешиваете указатели и данные.
Struct struct
определяет объект данных
void *data
ожидается, что data
это будет указатель.
Вызовите Foo
с указателем на Struct
и внесите другие необходимые изменения
Ответ №7:
Struct struct;
Foo((void*)amp;struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
или в более компактной форме:
Struct struct;
Foo((void*)amp;struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}