|
|
  |
Перенос кода в среду IAR |
|
|
|
Mar 14 2017, 09:45
|

Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191

|
Добрый день, коллеги! Переношу проект, написанный в AVR Studio 4 под WinAvr, в среду IAR Столкнулся с тем, что IAR ругается на такую конструкцию (ошибка Pe513): ssp.spiHwInit=(void *)atmega_spi_init; где объявления даны следующим образом: euint8 atmega_spi_init(atmegaSpiInterface *iface); и Код struct SdSpiProtocol { void *spiHwInterface; euint8 (*spiHwInit)(void* spiHwInterface); euint8 (*spiSendByte)(void* spiHwInterface,euint8 data); }; typedef struct SdSpiProtocol SdSpiProtocol; Подскажите, пожалуйста, как ее правильно описать в IAR?
Сообщение отредактировал IgorKossak - Mar 14 2017, 15:08
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!! Лишние пустые строки!
|
|
|
|
|
Mar 14 2017, 09:53
|

Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191

|
Цитата(scifi @ Mar 14 2017, 14:46)  Очевидно, компилируете в режиме Си++. Не надо так делать. Пусть будет просто тёплый ламповый Си. Да нет, проверил, в настройках стоит С. C dialect C99
|
|
|
|
|
Mar 14 2017, 10:10
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Василий Зыков @ Mar 14 2017, 12:53)  Да нет, проверил, в настройках стоит С. C dialect C99 А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор. Можно сделать вот так: Код ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init; Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие?
|
|
|
|
|
Mar 14 2017, 10:55
|

Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191

|
Цитата(scifi @ Mar 14 2017, 15:10)  А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор. Можно сделать вот так: Код ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init; Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие? Winavr такое проглатывает..... другой разработчик давно написал этот код. Работало и работало. Пока не появилась необходимость что-то поменять. Спасибо огромное! Заработало! Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Спасибо еще раз! Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает.
Сообщение отредактировал IgorKossak - Mar 14 2017, 15:09
Причина редактирования: бездумное цитирование
|
|
|
|
|
Mar 14 2017, 11:35
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Василий Зыков @ Mar 14 2017, 13:55)  теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Приведение к типу "указатель на функцию". Ну да, с непривычки странно выглядит. Цитата(Василий Зыков @ Mar 14 2017, 13:55)  Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает. Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа.
|
|
|
|
|
Mar 14 2017, 13:51
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(scifi @ Mar 14 2017, 18:35)  Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа. Так в первом сообщении всё есть. Поле в структуре описано как указатель на функцию, принимающую указатель на void и возвращающую euint8, а ему пытаются присвоить указатель на функцию, принимающую указатель на atmegaSpiInterface и возвращающую euint8. Ясное дело, без явного преобразования типа такое делать нельзя, и преобразование к типу void* не поможет. Вот если наоборот - полю типа void* можно присваивать любой указатель. Но тогда для вызова функции по такому указателю потребуется преобразование его типа в тип, соответствующий вызываемой функции, что открывает массу возможностей для ошибок. Вообще, передача в функции указателей на структуры и наличие в структурах указателей на функции верный признак того, что рамки С коду уже тесны и пора переходить на С++, а не заниматься имитацией на С классов и виртуальных функций.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Mar 14 2017, 13:52
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата(Василий Зыков @ Mar 14 2017, 12:55)  Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Более наглядная конструкция: *((void**)&ssp.spiHwInit) = (void*)atmega_spi_init;
|
|
|
|
|
Mar 14 2017, 15:29
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата(scifi @ Mar 14 2017, 16:05)  Так это же совсем другая семантика. Не будет работать, короче. Зависит от модели памяти: требуется совпадение физических размеров "DATA pointer" и "FUNC pointer", тогда будет работать. Но пример приведен как альтернатива для понимания. Правильно будет использовать Ваш вариант приведения.
|
|
|
|
|
Mar 15 2017, 05:52
|

Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191

|
Спасибо большое вам за комментарии и разъяснения! Цитата(aiwa @ Mar 14 2017, 18:52)  Более наглядная конструкция: *((void**)&ssp.spiHwInit) = (void*)atmega_spi_init; Нет, пожалуй, первая конструкция мне понятнее
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|