Форум РадиоКот https://radiokot.ru/forum/ |
|
Проблема макросов в классах. https://radiokot.ru/forum/viewtopic.php?f=57&t=111109 |
Страница 1 из 2 |
Автор: | Pink-Pank [ Чт дек 18, 2014 08:42:24 ] |
Заголовок сообщения: | Проблема макросов в классах. |
Всем добрый день! Частенько использую макросы для автоматизированного расчета загружаемых в регистры значений. Например: Код: #define F_CPU 1200000UL #define TIMER_FREQUENCY_HZ 1013 // Частота срабатывания таймера в герцах. #define LOAD_VALUE ((unsigned char)( round(((double)F_CPU / (double)TIMER_FREQUENCY_HZ / 8 - 1)))) .... OCR0 = LOAD_VALUE; // 8 - предделитель таймера. Режим CTC В общем, если использую подобные макросы при работе с регистрами напрямую или передавая значение функции, то все ОК. А на этот раз решил поиграться с классами. Создал класс и появилась проблемка. При передаче функции класса числового значения все ОК. Либо если передаю макрос, где нет приведения типов, то тоже все ОК. А вот если в макросе есть приведение типа переменной, то компилятор начинает материться, что: missing binary operator before token "(" Кто может сталкивался с такой проблемой? Как ее решить? Я так предполагаю, что препроцессор сначала подставляет выражение из макроса, а уже потом его рассчитывает. Может можно как-то заставить его сначала рассчитать это значение, а потом уже подставлять куда надо? Или как-то альтернативно решить эту проблему? Какой ентому гаду бинарный оператор нужен? И еще. Если я функции класса передаю не переменные, а числовые константы, можно как-то компилятор заставить, чтобы функция не принимала значения через стек (или регистры), а генерировалась инлайном с подстановкой нужных значений, не качая их из стека? Это с учетом того, что она в классе и простой инлайн не катит, но вызывается при этом всего один раз. |
Автор: | ploop [ Чт дек 18, 2014 09:34:27 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
У вас точка с запятой в макросе. Pink-Pank писал(а): Я так предполагаю, что препроцессор сначала подставляет выражение из макроса, а уже потом его рассчитывает Именно так. Pink-Pank писал(а): Если я функции класса передаю не переменные, а числовые константы, можно как-то компилятор заставить, чтобы функция не принимала значения через стек (или регистры), а генерировалась инлайном с подстановкой нужных значений, не качая их из стека? Нет. Функция есть функция, это машинный код в итоге. Препроцессор не сможет запустить её на исполнение в результате компиляции и оставить только результат, так как неизвестно, что там внутри функции вы наворотили. Ой, кажется не так вас понял И, кстати, что за классы вы используете? У вас C++? Цитата: то с учетом того, что она в классе и простой инлайн не катит, но вызывается при этом всего один раз. С чего это не может быть инлайновых методов? Вполне могут. |
Автор: | Pink-Pank [ Чт дек 18, 2014 09:54:36 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
В макросе у меня нет точек с запятой. Это я просто здесь "намешал" код и макросы. Щас поправлю. Да, я в студии 6 на си ++ изголяюсь. Хотя можно было бы все проще оформить - просто для опыта решил через класс. Цитата: С чего это не может быть инлайновых методов? Вполне могут. Не знаю. При попытке оформить метод как инлайн компилятор материться, что функция из класса не может вызываться, как инлайная. Думаю, проблема в области видимости внутренних функций классов или что-то в этом духе.. Ведь если сделать два разных объявления классов с одинаковым набором внутренних переменных, потом создать эти два класса и попытаться присвоить значения одного класса другому, то компиль также выдаст ошибку. Думаю, здесь что-то подобное.. |
Автор: | ploop [ Чт дек 18, 2014 10:10:36 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Думаю, вы что-то намутили... Во-первых давайте не будем называть "функции класса", они называются методы, иначе рвёт мозг. Pink-Pank писал(а): Ведь если сделать два разных объявления классов с одинаковым набором внутренних переменных, потом создать эти два класса и попытаться присвоить значения одного класса другому, то компиль также выдаст ошибку. Думаю, здесь что-то подобное.. Как вы это делаете? Ничего не понял, покажите пример. |
Автор: | Pink-Pank [ Чт дек 18, 2014 10:17:32 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Методы.. Шметоды.. Это все условности! ))) Главное - полет мысли! )))))) Но если Вам так привычнее - пожалуйста! Мне не трудно. ) Код: class First { int memi; double memd; }; class Second { int memi; double memd; }; class First obj1; Second obj2 = obj1; // ошибка: obj1 и obj2 имеют разные типы Да и как я мог намутить, если передача обычного числа, макроса или переменной прокатывает, а макрос с преобразованием типов вызывает ошибку? Т.е. если я передаю выражение, скажем F_CPU/16, то все ок. А если выражение (uint16_t)((double)F_CPU/16), то получается облом... Хотя при передаче в простую функцию второе выражение норм работает. |
Автор: | ploop [ Чт дек 18, 2014 10:46:29 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): // ошибка: obj1 и obj2 имеют разные типы Естественно! Первый имеет тип First, второй - Second. А если они внутри одинаковы - так это ваша проблема, так как такой подход рвёт все шаблоны ООП. Pink-Pank писал(а): А если выражение (uint16_t)((double)F_CPU/16), то получается облом... Ошибка то хоть какая? |
Автор: | Pink-Pank [ Чт дек 18, 2014 10:52:31 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
я ж писал missing binary operator before token "(" |
Автор: | Siarzhuk [ Чт дек 18, 2014 11:28:52 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): А вот если в макросе есть приведение типа переменной, то компилятор начинает материться, что: missing binary operator before token "(" Кто может сталкивался с такой проблемой? Как ее решить? Я так предполагаю, что препроцессор сначала подставляет выражение из макроса, а уже потом его рассчитывает. С какой проблемой? Где кот с классами? Телепатам гадать не на чем. ![]() При непонятных проблемах с макросами нужно включать опцию -F Preprocess only результат работы препроцессора будет сохранен в файле с расширением *.i а компиляция не будет производиться. При нормальной компиляции этот вот *.i и скармливается компилятору. Обычно достаточно одного взгляда на развёрнутый макрос чтобы понять в чём проблема. Для inline попробуйте определить тело функции прямо v определении класса в h файле. А вообще нужно читать мануал на компилятор соответствующую тему - там наверняка оговариваются нюансы использования. Pink-Pank писал(а): Да и как я мог намутить, Мутят все, мутили и будут мутить всегда и вовеки - чем вы лучше других? Как и во всяком ремесле опыт решает - другие просто эти шишки уже собрали на свои головы пока вы прохлаждались - вот и всё. Pink-Pank писал(а): // ошибка: obj1 и obj2 имеют разные типы Определите операторы присваивания и будет вам счастье. Это нужно делать даже для одинаковых типов если они имеют ссылки на внешние ресурсы - по умолчанию компилятор создает оператор присваивания с простым копированием данных если оператор=(...) для этого типа не задан прокладкой между стулом и клавиатурой. |
Автор: | Pink-Pank [ Чт дек 18, 2014 11:51:51 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Цитата: Для inline попробуйте определить тело функции прямо v определении класса в h файле. А вообще нужно читать мануал на компилятор соответствующую тему - там наверняка оговариваются нюансы использования. Уже пробовал.. Не помогает.. Цитата: С какой проблемой? Где кот с классами? Да что Вам мой кот, если компилятор глотает обычные числовые значения и макросы без преобразования типов. Цитата: Определите операторы присваивания и будет вам счастье. поподробнее можно? Что-то я не очень понял, о чем Вы? Вы про перегрузку операторов? Цитата: -F Preprocess only не -F, а -E Сейчас попробую. Что-то не генерится этот файл.. Выдает ошибку ld returned 1 exit status collect2.exe 0 0 |
Автор: | Siarzhuk [ Чт дек 18, 2014 12:13:54 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): Цитата: С какой проблемой? Где кот с классами? Да что Вам мой кот, если компилятор глотает обычные числовые значения и макросы без преобразования типов. А без кота разговор беспредметен. Ну глотает, и чо? А вот нужные вам макросы не глотает. Не переваривает стало-быть их. Несъедобно готовите раз котейко давится. Скобок туда по уму добавьте - сожрёць как миленький - и не такое сжирал. И ещё раз про *.i выхлоп напоминаю - дюже важный доку́мент для пущего понимания процессов "прокладкой". |
Автор: | Siarzhuk [ Чт дек 18, 2014 12:22:04 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): Вы про перегрузку операторов? да, они, что-то типа Код: Second* Second::operator=(const First& first) { // тут присвоЯем поля return *this; } Pink-Pank писал(а): Цитата: -F Preprocess only не -F, а -E Сейчас попробую. Что-то не генерится этот файл.. Выдает ошибку ld returned 1 exit status collect2.exe 0 0 Ну может и не -F и не *.i - вам на месте виднее - гляньте в папках где временные файлы/результаты компиляции - может какие *.pre или что-то в этом роде сохраняется - а сообщение означает что линкер не нашёл чего хотел - т.е. как-бы понятно почему - объектников-то ведь нету - один препроцессор. удачи. |
Автор: | Pink-Pank [ Чт дек 18, 2014 12:25:57 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Цитата: Несъедобно готовите раз котейко давится. Скобок туда по уму добавьте - сожрёць как миленький - и не такое сжирал. Видно, скобочками и давится - потому что у меня их как раз валом! ![]() А как Вам тот факт, что тот же макрос обычной функцией принимается без проблем? ![]() Вот Вам мой класс *.h СпойлерКод: #ifndef __Usart_H__ #define __Usart_H__ #include <avr\io.h> #define INLINE inline __attribute__((__always_inline__)) #define NOINLINE __attribute__((__noinline__)) typedef enum { UART = (0 << UMSEL), // Режим работы UART USART = (1 << UMSEL) // Режим работы USART } Work_regim_Def; typedef enum { _5_bit = 0, // Ширина посылки 5 бит _6_bit = 1, // Ширина посылки 6 бит _7_bit = 2, // Ширина посылки 7 бит _8_bit = 3, // Ширина посылки 8 бит _9_bit = 0b111 // Ширина посылки 9 бит } Character_Size_Def; typedef enum { No_Par = (0 << UPM0), // Нет бита четности Even = (0b10 << UPM0), // Дополнение до четного Odd = (0b11 << UPM0) // Дополнение до нечетного } Parity_Mode_Def; typedef enum { _1_stop = (0 << USBS), // 1 стоп-бит _2_stop = (1 << USBS) // 2 стоп-бита } Stop_Bit_Def; typedef enum { T_Rising = (0 << UCPOL), // В синхроннном режиме выдача данных по нарастающему фронту T_Falling = (1 << UCPOL), // В синхронном режиме выдача данных по спадающему фронту R_Rising = T_Falling, R_Falling = T_Rising } Polarity_Def; typedef enum { Normal = (0 << U2X), // нормальная скорость передачи Double = (1 << U2X) // Двойная скорость передачи } Double_Speed_Def; typedef enum { Alone = (0 << MPCM), // Режим точка-точка Multi = (1 << MPCM) // Мультипроцессорный режим } Multiproc_Def; class Usart { //variables public: protected: private: //functions public: Usart(); ~Usart(); void Init (uint16_t Baud_rate = 2400U, Work_regim_Def Work_regim = UART, Character_Size_Def Character_Size = _8_bit, Parity_Mode_Def Parity_Mode = No_Par, Stop_Bit_Def Stop_Bit = _1_stop, Polarity_Def Polarity = T_Rising, Double_Speed_Def Double_Speed = Normal, Multiproc_Def Multiproc = Alone); protected: private: }; //USART #endif //__USART_H__ Вот мой класс *.cpp СпойлерКод: #include "Usart.h" #include <avr\io.h> // default constructor Usart::Usart() { } //USART // default destructor Usart::~Usart() { } //~USART void Usart::Init (uint16_t Baud_rate, Work_regim_Def Work_regim, Character_Size_Def Character_Size, Parity_Mode_Def Parity_Mode, Stop_Bit_Def Stop_Bit, Polarity_Def Polarity, Double_Speed_Def Double_Speed, Multiproc_Def Multiproc) { UBRRL = Baud_rate; } Вот моя функция с вызовом и подстановкой макроса: СпойлерКод: #define F_CPU 1200000UL #include <avr\io.h> #include <util\delay.h> #include <avr\interrupt.h> //#include <math.h> #include "Pins.h" #include "Usart.h" // мой класс #define BOAD_RATE 500 // Если синхронный режим //#define UBRR (uint16_t)((round((double)F_CPU/2.0/BOAD_RATE))-1) // Асинхронный с включенным удвоением скорости //#define UBRR (uint16_t)((round((double)F_CPU/8.0/BOAD_RATE))-1) // Асинхронный с нормальной скоростью #define UBRR (uint16_t)((round((double)F_CPU/16.0/BOAD_RATE))-1) //#define UBRR (500) //#define UBRR (F_CPU/16) class Usart uart; __attribute__((OS_main)) int main(void) { uart.Init(UBRR, UART, _8_bit); } |
Автор: | Siarzhuk [ Чт дек 18, 2014 12:36:37 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): Цитата: Несъедобно готовите раз котейко давится. Скобок туда по уму добавьте - сожрёць как миленький - и не такое сжирал. Видно, как раз скобочками и давится - потому что у меня их как раз валом! ![]() А как Вам тот факт, что тот же макрос обычной функцией принимается без проблем? ![]() Ничего удивительного - даже если макрос не огорожен скобками - результат исчисления по любому уйдёт в функцию, а вот неогороженный макрос в выражении имеет все шансы быть растащенным в стороны операциями с более высоким приоритетом. Типовая ошибка - потому в любом букваре по сишному препроцессору есть соответствующие примеры и страшилки. |
Автор: | ploop [ Чт дек 18, 2014 14:02:46 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
У вас проблема точно в макросе? Раз ругается на битовую операцию, значит может быть в структуре Work_regim_Def, что после него идёт? Вы кажется намутили с областью видимости индентификатора UART |
Автор: | Pink-Pank [ Чт дек 18, 2014 14:42:32 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
то, что идет после никакого отношения к ошибке не имеет. Я те параметры пробовал и вовсе комментировать, оставлял только один, который не робит. Не помогло. Перечисления я там сделал, чтобы вводимые значения в качестве параметров были фиксированными. Чтобы пользователь класса не мог запулить туда что-то не удобоваримое. Да и при нажатии на ошибку выкидывает именно на макрос. Попробую в IAR загнать.. если схавает - значит студия ка-ка. Если нет и с такой же ошибкой - значит ка-ка я! ![]() |
Автор: | Siarzhuk [ Чт дек 18, 2014 17:07:33 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): Код: //#include <math.h> А функция round точно видна и не перекрывается переменной с таким именем? Да и %s/BOAD/BAUD/g надо бы сделать. ![]() |
Автор: | Pink-Pank [ Пт дек 19, 2014 07:33:56 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Видна. У меня нет таких переменных. |
Автор: | Аlex [ Пт дек 19, 2014 07:57:40 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
А если её (round) для пробы выкинуть из макроса, проглотит ? ИМХО, для начала нужно методом исключения узнать, что конкретно "мешается" в макросе, а потом уже думать почему так происходит. |
Автор: | Siarzhuk [ Пт дек 19, 2014 10:55:49 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Pink-Pank писал(а): Видна. У меня нет таких переменных. Т.е. если написать пару строками раньше что-то типа double d = round(2342.346456); компилятор скушает и не ругнётся? ну разбивайте макрос по операциям на разных строчках с промежуточными результатами и смотрите на какой чертыхнётся если лень выхлоп препроцессора искать и времени не жалко. В порядке постукивания по бубну оберните всю подстановку в скобки. Или воспользуйтесь конструкторо-подобной нотацией оператора приведения: Код: #define UBRR uint16_t( round( double(F_CPU) / 16.0 / BOAD_RATE ) - 1)
|
Автор: | BCluster [ Пт дек 19, 2014 12:37:19 ] |
Заголовок сообщения: | Re: Проблема макросов в классах. |
Проверил в IAR ARM такую конструкцию, она работает |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |