wizzard: (Default)
[personal profile] wizzard

#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).

Date: 2010-01-03 09:49 pm (UTC)
From: [identity profile] sashman.livejournal.com
Что интересно (и очевидно),
#define MV_TO_ADC(MV, R_PU, R_PD) (((((MV)*1024)/(ADC_V_REF))*(R_PD))/((R_PU)+(R_PD)))
работает нормально.

т.е. в cc не выполняются базовые законы математики. И никаких ворнингов, что особо противно.

Тысячи желчи на разработчиков.

Date: 2010-01-03 11:10 pm (UTC)
From: [identity profile] faceted-jacinth.livejournal.com
Проверил на msvc 2008, в обоих режимах (х64 и х32).

Во-первых, он тебе выдаёт варнинг.

Во-вторых, запомни: типы long, unsigned long, и соответствующие константы использовать нельзя, вместо них следует использовать long long, unsigned long long и LL/ULL суффиксы, а ещё лучше - подключить types.h или как там её, где объявлены int64_t сотоварищи. Ну или накрайняк самому себе написать. Я к тому, что так всё работает правильно вощемта.

Profile

wizzard: (Default)
wizzard

January 2019

S M T W T F S
  12 345
6789101112
1314 1516171819
202122 23242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 6th, 2026 03:54 am
Powered by Dreamwidth Studios