[英]How to fix implicit signed to unsigned conversion, warning 373
我知道这已经被问过几次了,但我并不清楚答案。
此警告似乎与编译器将类型 char 提升为 unsigned char ......
我在str[numbytes-i] = r + 0x30;
下面 function 的两个地方收到警告。 .
解决这个问题的正确方法是什么?
void usitoh( UINT16 val, UINT8 numbytes, char *str ) //extern
{
UINT8 i = 0;
UINT8 r = 0;
//Convert the Base 10 Number to Base 16
//Starting with LSB (i=1) and work to the MSB
for (i=1; i <= numbytes; i++)
{
r = val % 16; //Get the MOD of the number
//The MOD of the number represents the Hex value
val = val / 16; //Get the Quotient of the number
//Load the value into the string and
//add an offset to generate ASCII values
// '0' = 0x30, 'A' = 0x41
if (r <= 9) //Values < A
{
//For values 0-9 the ASCII offset is 0x30
//This produces and offset to get to chars 0,1,2,3,4,5,6,7,8,9
//Warning 373 issue
str[numbytes-i] = r + 0x30;
}
else //Values > 9
{
//The MOD of the number represents the Hex value
//For values 0-9 the ASCII offset is 0x41 to get to "A" and - 0x0A to account 0-9 numbers
//This produces and offset to get to chars A,B,C,D,E,F
//Warning 373 issue
str[numbytes-i] = r + (0x41 - 0x0A);
}
}//END of FOR Loop
}//END of "usitoh"
更新:
谢谢大家的建议和建议。
@chux 我真的很喜欢你的“替代代码”和@Persixty 更简洁的选项。
按照建议键入大小写已修复此问题。
关于代码的一点背景故事。
我继承了这段代码,作为重新设计一些硬件的项目的一部分,客户让我们相信这段代码是一个很好的起点…… 嗯……我们上了诱饵、钩子、线和坠子。
代码用 MPLAB、XC8 编译器编写。
硬件既快速又简单,但是一旦我们开始修改代码,我们发现它是史诗般的混乱,我从未见过如此意大利面条式的 C 代码。 感觉就像汇编代码。 随着我们继续深入,我们发现了几个问题。
我们不断遇到奇怪的崩溃和编译问题。
经过一番催促,我们发现代码是由一位企业家创建的,并交给了一个咨询小组,该小组有几个人破解它。
因此,大写类型是原作者的产物。 谁在自己的 header 文件中定义了它们。
gcc -Wall -Wextra
没有给我这个修订版的任何警告:
#include <stdint.h>
void usitoh(uint16_t val, uint8_t numbytes, char *str ) {
for (uint8_t i=0; i < numbytes; i++) {
uint8_t r = val % 16;
val = val / 16;
str[numbytes-i+1] = r + ((r <= 9) ? '0' : 'A' - '\n');
}
}
可以使用演员表。 不优雅,但会消除警告。
// str[numbytes-i] = r + 0x30;
str[numbytes-i] = (char) (r + 0x30);
...
// str[numbytes-i] = r + (0x41 - 0x0A);
str[numbytes-i] = (char) (r + (0x41 - 0x0A));
稍后替换代码。 GTG。
答案就在警告本身。 编译器只是警告你一个隐式操作,它被认为容易出错,你可能不会立即明白这会如何导致错误,但这就是为什么警告在这里提醒你三思而后行的原因是正确的。
例如,取一个 int,并将其分配给一个 char。 在您的微控制器上,您的 int 很可能是 16 位,而 char 只有 8 位。 如果您的 integer 值足够大,您将丢失多达一半的位,如果您不打算发生这种情况,这是很糟糕的。 这是此警告的唯一目的 - 警告您不打算发生的事情可能会发生。
正确的做法是始终重新检查这是否是您的意思,然后通过强制转换使其明确。 这样编译器就知道你真的打算在两种不同的类型之间进行转换,可能是从一种缩小到另一种,并且你还检查了这些类型是否真的需要在这里转换。
答案就在警告本身。 编译器只是警告你一个隐式操作,它被认为容易出错,你可能不会立即明白这会如何导致错误,但这就是为什么警告在这里提醒你三思而后行的原因是正确的。
例如,取一个 int,并将其分配给一个 char。 在您的微控制器上,您的 int 很可能是 16 位,而 char 只有 8 位。 如果您的 integer 值足够大,您将丢失多达一半的位,如果您不打算发生这种情况,这是很糟糕的。 这是此警告的唯一目的 - 警告您不打算发生的事情可能会发生。
错误的另一个原因是从unsigned char
转换为char
,您的UINT8
可能只是 unsigned char 的 typedef。 char 是一种特殊情况,它可能是有符号或无符号的,因此编译器必须发出警告以提醒您在无符号类型与无论如何都具有实现定义的符号的类型之间发生转换。
正确的做法是始终重新检查这是否是您的意思,然后通过强制转换使其明确。 这样编译器就知道你真的打算在两种不同的类型之间进行转换,可能是从一种缩小到另一种,并且你还检查了这些类型是否真的需要在这里转换。
最谨慎的编译器选项应该接受:
str[numbytes-i] = '0' + ((char)r) ;
我会说这是意图最自然的表达。
“将数字视为char
从零开始计数( 0
)”。
也就是说,我想说最明确的解决方案是:
str[numbytes-i] = HEX_DIGITS[r]
用static const char HEX_DIGITS[]="0123456789ABCDEF";
上面声明的。
它删除了if
语句,甚至是最轻微的字符集巧妙性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.