C语言 C:警告的解决方法:表达式中的整数溢出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2347851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:39:14  来源:igfitidea点击:

C: A cure for the warning: integer overflow in expression?

cembedded

提问by Hamza

I am trying to organise my UART library and prettify it a little bit by adding some #define s so I can customize it later without having to dig deeply into the code, but I can't seem to get the following bit of code working:

我正在尝试组织我的 UART 库并通过添加一些 #define 来稍微美化它,以便我以后可以自定义它而无需深入研究代码,但我似乎无法让以下代码工作:

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

void uart_init(){
   U1BRG = BRGVAL;
}

After the calculation BRGVAL becomes 25.0416667, and because it is not an integer I get the following warning for it when I assign that into U1BRG:

计算后 BRGVAL 变为 25.0416667,因为它不是整数,所以当我将它分配给 U1BRG 时,我收到以下警告:

UART.c: In function 'uart_init':

UART.c:24: warning: integer overflow in expression

UART.c:在函数“uart_init”中:

UART.c:24:警告:表达式中的整数溢出

...and the code simply does not work on target hardware. (If I manually put in U1BRG = 25 it works like a charm though)

...并且代码根本无法在目标硬件上运行。(如果我手动输入 U1BRG = 25 它就像一个魅力)

Is there any way to typecast that constant into an integer to make the compiler happy?

有没有办法将该常量类型转换为整数以使编译器满意?

Many Thanks, Hamza.

非常感谢,哈姆扎。

回答by Philip Potter

Integer overflow means that you have exceeded the upper limit of an int value, which is likely to be 32767 if you are getting this error. It has nothing to do with floating point; the operations you have specified are in fact integer math operations, so the fractional part of the division is discarded anyway.

整数溢出意味着您已超出 int 值的上限,如果您收到此错误,则可能是 32767。它与浮点无关;您指定的运算实际上是整数数学运算,因此无论如何都会丢弃除法的小数部分。

Try something like this:

尝试这样的事情:

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

void uart_init(){
   U1BRG = BRGVAL;
}

The L suffix turns these constants into longtype instead of inttype. The (unsigned int)cast converts to U1BRG's type, and lets the compiler know that you understand that the longvalue will fit into an unsigned intand thus hide any warnings it may throw at you.

L 后缀将这些常量转换为long类型而不是int类型。该(unsigned int)投皈依U1BRG的类型,并让编译器知道你明白long价值将适合的unsigned int,从而隐藏其可以在你扔任何警告。

Normally, it's bad practice to silence compiler warnings, but in this case, it's clear that although you need longto store intermediate values in the calculation, the final result will fit into an unsigned int.

通常,使编译器警告静音是不好的做法,但在这种情况下,很明显,虽然您需要long在计算中存储中间值,但最终结果将适合unsigned int.

回答by tomlogic

I like Philip's answer, but I think a better solution is to reduce the formula and change your macro to:

我喜欢菲利普的回答,但我认为更好的解决方案是减少公式并将宏更改为:

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

In doing so, you eliminate the cast so the compiler can continue to warn you if you choose a low baud rate that would result in a divider value too large for a 16-bit int.

这样做时,您消除了强制转换,以便编译器可以在您选择低波特率时继续警告您,这会导致分频器值对于 16 位 int 来说太大。

回答by Segfault

I would probably use this:

我可能会使用这个:

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

回答by t0mm13b

You have failed to point this out, What's the data type for U1BRG? If it's an int, cast it like as shown

您没有指出这一点,U1BRG 的数据类型是什么?如果是int,则如图所示进行投射

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

void uart_init(){
   U1BRG = BRGVAL;
}

Edit:Amended this to take into consideration of Adam Liss's comment that an unsigned int is too small to hold the result of the macro, I have changed it to make it a long...Thanks Adam for the headsup...

编辑:修改此以考虑到Adam Liss的评论,即 unsigned int 太小而无法保存宏的结果,我已将其更改为long...感谢 Adam 的提醒...

Hope this helps, Best regards, Tom.

希望这会有所帮助,最好的问候,汤姆。

回答by JSB????

It's not clear from your example whether U1BRG is a global variable or a #define'ed constant. In any case, simply casting to an integer should work:

从您的示例中不清楚 U1BRG 是全局变量还是 #define'ed 常量。在任何情况下,简单地转换为整数应该可以工作:

 U1BRG = (int)BRGVAL;