C: Средство исправления для предупреждения: целочисленное переполнение в выражении?

Я пытаюсь организовать свою библиотеку UART и украсить ее немного путем добавления некоторого #define s, таким образом, я могу настроить ее позже, не имея необходимость рыть глубоко в код, но я, может казаться, не получаю следующий бит работы кода:

#define FOSC        8000000
#define BAUDRATE    9600
#define BRGVAL      (FOSC/2)/(16*BAUDRATE)-1

void uart_init(){
   U1BRG = BRGVAL;
}

После вычисления BRGVAL становится 25.0416667, и потому что это не целое число, я получаю соблюдающее предупреждение для него, когда я присваиваю это в U1BRG:

UART.c: В функции 'uart_init':

UART.c:24: предупреждение: целочисленное переполнение в выражении

... и код просто не работает над целевыми аппаратными средствами. (Если я вручную вставил U1BRG = 25, он работает как очарование хотя),

Там какой-либо путь состоит в том, чтобы преобразовать тип той константы в целое число для создания компилятора счастливым?

Большое спасибо, гамза.

9
задан Hamza 27 February 2010 в 15:31
поделиться

5 ответов

Целочисленное переполнение означает, что вы превысили верхний предел значения int, которое, вероятно, будет 32767, если вы получаете эту ошибку. Это не имеет ничего общего с плавающей точкой; указанные вами операции на самом деле являются целочисленными математическими операциями, поэтому дробная часть деления в любом случае отбрасывается.

Попробуйте что-то вроде этого:

#define FOSC        8000000L
#define BAUDRATE    9600L
#define BRGVAL      ((unsigned int)((FOSC/2)/(16*BAUDRATE)-1))

void uart_init(){
   U1BRG = BRGVAL;
}

Суффикс L превращает эти константы в тип long вместо типа int . Приведение (unsigned int) преобразуется в тип U1BRG и сообщает компилятору, что вы понимаете, что значение long впишется в unsigned int и, таким образом, скроет любые предупреждения, которые он может вам бросить.

Обычно отключать предупреждения компилятора - плохая практика, но в этом случае ясно, что, хотя вам понадобится long для хранения промежуточных значений в вычислениях, конечный результат будет соответствовать беззнаковым int .

24
ответ дан 4 December 2019 в 07:04
поделиться

Из вашего примера не ясно, является ли U1BRG глобальной переменной или константой, определяемой #. В любом случае простое приведение к целому числу должно работать:

 U1BRG = (int)BRGVAL;
0
ответ дан 4 December 2019 в 07:04
поделиться

Вы не смогли указать на это, какой тип данных у U1BRG? Если это int , приведите его как показано

#define FOSC        8000000
#define BAUDRATE    9600
#define BRGVAL      ((long)(FOSC/2)/(16*BAUDRATE)-1)

void uart_init(){
   U1BRG = BRGVAL;
}

Edit: Исправлено, чтобы принять во внимание комментарий Адама Лисса о том, что беззнаковое int слишком мало для сохранить результат макроса, я изменил его, чтобы сделать его длинным ... Спасибо Адаму за предупреждение ...

Надеюсь, это поможет, С уважением , Том.

0
ответ дан 4 December 2019 в 07:04
поделиться

Я бы, вероятно, использовал это:

#define BRGVAL      ((int)(FOSC/2)/(16*BAUDRATE)-1)
0
ответ дан 4 December 2019 в 07:04
поделиться

Мне нравится ответ Филиппа, но я думаю, что лучшим решением будет сократить формулу и изменить макрос на:

#define BRGVAL (FOSC/32/BAUDRATE-1)

При этом вы устраняете cast, чтобы компилятор мог продолжать предупреждать вас, если вы выберете низкую скорость передачи данных, что приведет к слишком большому значению делителя для 16-битного int.

8
ответ дан 4 December 2019 в 07:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: