ArcherVZ 0 March 14, 2017 Posted March 14, 2017 (edited) · Report post Добрый день, коллеги! Переношу проект, написанный в 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? Edited March 14, 2017 by IgorKossak [codebox] для длинного кода. [code]-для короткого!!! Лишние пустые строки! Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 March 14, 2017 Posted March 14, 2017 · Report post Очевидно, компилируете в режиме Си++. Не надо так делать. Пусть будет просто тёплый ламповый Си. Quote Share this post Link to post Share on other sites More sharing options...
ArcherVZ 0 March 14, 2017 Posted March 14, 2017 · Report post Очевидно, компилируете в режиме Си++. Не надо так делать. Пусть будет просто тёплый ламповый Си. Да нет, проверил, в настройках стоит С. C dialect C99 Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 March 14, 2017 Posted March 14, 2017 · Report post Да нет, проверил, в настройках стоит С. C dialect C99 А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор. Можно сделать вот так: ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init; Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие? Quote Share this post Link to post Share on other sites More sharing options...
ArcherVZ 0 March 14, 2017 Posted March 14, 2017 (edited) · Report post А, не заметил, что, очевидно, указатель на функцию приводите к void* и присваиваете другому указателю на функцию. Это безобразие. Если какой-то компилятор такое проглатывал, то это неправильный компилятор. Можно сделать вот так: ssp.spiHwInit=(euint8 (*)(void*))atmega_spi_init; Но необходимость приведения типа указателя на функцию настораживает, конечно. Кто придумал всё это безобразие? Winavr такое проглатывает..... другой разработчик давно написал этот код. Работало и работало. Пока не появилась необходимость что-то поменять. Спасибо огромное! Заработало! Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Спасибо еще раз! Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает. Edited March 14, 2017 by IgorKossak бездумное цитирование Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 March 14, 2017 Posted March 14, 2017 · Report post теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Приведение к типу "указатель на функцию". Ну да, с непривычки странно выглядит. Почему-то без приведения типа компилятор тоже выдает ошибку... меня это тоже смущает. Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа. Quote Share this post Link to post Share on other sites More sharing options...
SSerge 0 March 14, 2017 Posted March 14, 2017 · Report post Надо смотреть, какой тип у ssp.spiHwInit. Очевидно, какой-то другой, раз компилятор жалуется без приведения типа. Так в первом сообщении всё есть. Поле в структуре описано как указатель на функцию, принимающую указатель на void и возвращающую euint8, а ему пытаются присвоить указатель на функцию, принимающую указатель на atmegaSpiInterface и возвращающую euint8. Ясное дело, без явного преобразования типа такое делать нельзя, и преобразование к типу void* не поможет. Вот если наоборот - полю типа void* можно присваивать любой указатель. Но тогда для вызова функции по такому указателю потребуется преобразование его типа в тип, соответствующий вызываемой функции, что открывает массу возможностей для ошибок. Вообще, передача в функции указателей на структуры и наличие в структурах указателей на функции верный признак того, что рамки С коду уже тесны и пора переходить на С++, а не заниматься имитацией на С классов и виртуальных функций. Quote Share this post Link to post Share on other sites More sharing options...
aiwa 0 March 14, 2017 Posted March 14, 2017 · Report post Только... теперь я не понимаю, как эта конструкция построена. Так сложно на первый взгляд. Более наглядная конструкция: *((void**)&ssp.spiHwInit) = (void*)atmega_spi_init; Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 March 14, 2017 Posted March 14, 2017 · Report post Более наглядная конструкция: *((void**)&ssp.spiHwInit) = (void*)atmega_spi_init; Так это же совсем другая семантика. Не будет работать, короче. Quote Share this post Link to post Share on other sites More sharing options...
aiwa 0 March 14, 2017 Posted March 14, 2017 · Report post Так это же совсем другая семантика. Не будет работать, короче. Зависит от модели памяти: требуется совпадение физических размеров "DATA pointer" и "FUNC pointer", тогда будет работать. Но пример приведен как альтернатива для понимания. Правильно будет использовать Ваш вариант приведения. Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 March 14, 2017 Posted March 14, 2017 · Report post Но пример приведен как альтернатива для понимания. Что-то я в звёздочках запутался. Вроде бы должно и эдак получиться :laughing: Quote Share this post Link to post Share on other sites More sharing options...
ArcherVZ 0 March 15, 2017 Posted March 15, 2017 · Report post Спасибо большое вам за комментарии и разъяснения! Более наглядная конструкция: *((void**)&ssp.spiHwInit) = (void*)atmega_spi_init; Нет, пожалуй, первая конструкция мне понятнее :) Quote Share this post Link to post Share on other sites More sharing options...