препроцессор буэээ (проблема решена)
Jan. 3rd, 2010 11:41 pm#define R_PU_33 17890UL
#define R_PD_33 988UL
#define ADC_V_REF 2560UL
#define MV_TO_ADC(MV, R_PU, R_PD) (((MV)*(unsigned long)1024UL*(R_PD))/((ADC_V_REF)*((R_PU)+(R_PD))))
int _tmain(int argc, _TCHAR* argv[])
{
unsigned long i=0;
i=MV_TO_ADC(33000UL, R_PU_33, R_PD_33);
printf("%l", i);
return 0;
}
Этот код печатает “68” из-за integer overflow в числителе, несмотря на то, что везде где можно воткнуты unsigned long, и правильный ответ 690.
Что делать? Вручную раскрывать макросы не хочется, их подобных много. Проверено на msvc, gcc и avr-gcc (ATMEL).
no subject
Date: 2010-01-03 09:49 pm (UTC)#define MV_TO_ADC(MV, R_PU, R_PD) (((((MV)*1024)/(ADC_V_REF))*(R_PD))/((R_PU)+(R_PD)))работает нормально.
т.е. в cc не выполняются базовые законы математики. И никаких ворнингов, что особо противно.
Тысячи желчи на разработчиков.
no subject
Date: 2010-01-03 11:10 pm (UTC)Во-первых, он тебе выдаёт варнинг.
Во-вторых, запомни: типы long, unsigned long, и соответствующие константы использовать нельзя, вместо них следует использовать long long, unsigned long long и LL/ULL суффиксы, а ещё лучше - подключить types.h или как там её, где объявлены int64_t сотоварищи. Ну или накрайняк самому себе написать. Я к тому, что так всё работает правильно вощемта.
no subject
Date: 2010-01-03 11:15 pm (UTC)Алсо, подумай над тем, чтобы всё-таки заменять эту порнуху на static const и inline функции потихоньку!
no subject
Date: 2010-01-03 11:47 pm (UTC)no subject
Date: 2010-01-03 11:48 pm (UTC)no subject
Date: 2010-01-04 12:06 am (UTC)какбэ речь про 8-битные микроконтроллеры о сотнях байт ОЗУ и килобайтах флеша под код, так что порнуха иногда необходима.
кстати, если параметры макроса переменные - имеем инлайн-вычисление. Константы - константу.
в случае же заворачивания в функцию - набоум компилятора, заоптимизирует - не заоптимизирует.
no subject
Date: 2010-01-04 09:35 am (UTC)no subject
Date: 2010-01-04 09:39 am (UTC)no subject
Date: 2010-01-04 10:11 am (UTC)2. Макрос/функция - на самом деле, не столь принципиально. И в любом случае будет переписано для хранение констант в ээпроме.
no subject
Date: 2010-01-04 02:11 pm (UTC)а. препроцессор не при чем, он ничего не вычисляет в данном случае, он просто подставляет текст. Вычисляет компилятор, либо процессор (если компилятор не схлопнул выражение в константу).
б. Базовые законы математики вообще не выполняются в целочисленной арифметике, с учетом truncate при делении и under/overflow :)
no subject
Date: 2010-01-04 02:11 pm (UTC)no subject
Date: 2010-01-04 02:42 pm (UTC)мне всё равно, кто будет считать, препроцессор, компилятор или вообще линкер, лишь бы не таргет процессор, и не программист с калькулятором.
б. втихаря же не выполняются.
no subject
Date: 2010-01-04 03:29 pm (UTC)В 64битном gcc лонг всё-таки восьмибайтный, но под рукой его нет, чтобы посмотреть, как там с константами!