C 将字符强制转换为uint将设置所有MSB
我想知道为什么一行字符转换为无符号整数(uint16\u t或更高)会将所有位8-15设置为1。而两步铸造使钻头8-15保持在0。我是否做错了/奇怪了,还是在将字符转换为大于8位的整数时,始终使用C 将字符强制转换为uint将设置所有MSB,c,casting,char,int,C,Casting,Char,Int,我想知道为什么一行字符转换为无符号整数(uint16\u t或更高)会将所有位8-15设置为1。而两步铸造使钻头8-15保持在0。我是否做错了/奇怪了,还是在将字符转换为大于8位的整数时,始终使用&0xFF的“安全”方法?例如,在下面的代码中,如果我这样做,b将获得正确的值: uint16_t b = (uint16_t) ((*readChar)[0] & 0xFF); 代码:(我把额外的printf放在最后,以防打印值的第一个printf欺骗了我) #包括 #包括 void Get
&0xFF
的“安全”方法?例如,在下面的代码中,如果我这样做,b
将获得正确的值:
uint16_t b = (uint16_t) ((*readChar)[0] & 0xFF);
代码:(我把额外的printf
放在最后,以防打印值的第一个printf
欺骗了我)
#包括
#包括
void GetChar(char**);
int main(){
char*readChar;
GetChar(&readChar);
返回0;
}
void GetChar(char**readChar){
uint16_t val=3001;
uint16_t*valPtr=&val;
*readChar=(char*)valPtr;
uint8_t a=(*readChar)[0];//185
uint16_t b=(uint16_t)(*readChar)[0];//65465=b'1111111111011001'
uint16_t c=(uint16_t)a;//185=b'0000 0000 1011 1001'
printf(“%u%u%u”,a,b,c);//在您的系统上,char
的范围为-128到127。(这是常见的)。它不能像您建议的那样保存值185。您调用的值实际上是256-185,即-71
将-71
转换为无符号16位定义为65536-71
,即65465
(所有负整数到无符号的转换都是这样进行的)
您可以使用(uint8\t)一种将-71
转换为185
的技术;或者首先使用uint8
而不是char
。是编译器的char
签名,其值在0x80
到0xFF
的范围内。例如,如果char
值是-1
,您会怎么想转换为uint16\t
?请给出一些具体示例。@WeatherVane上面示例中的值3001是否不够具体?我不知道编译器的字符符号设置。这不是一个设置,而是一个编译器定义。char
可能有符号或无符号,取决于实现。假设您有char a=0xFF;printf(“%d\n”,a);
输出将是-1
或255
。回答得好。问题是,代码在微控制器上运行,似乎完美无瑕,这是在我编写和运行win/cygwin的单元测试时发生的。但是,实现(uint16\t)为了单元测试而使用的技巧也许不是一个坏主意。问题仍然是为什么b和c被区别对待…?@niCkcAMel我的回答已经解释过了。b
被赋值为(uint16_t)-71
,也就是65465
,而c
被赋值为(uint16_t)185
这是185
。
#include <stdlib.h>
#include <stdio.h>
void GetChar(char**);
int main() {
char* readChar;
GetChar(&readChar);
return 0;
}
void GetChar(char** readChar) {
uint16_t val = 3001;
uint16_t* valPtr = &val;
*readChar = (char*) valPtr;
uint8_t a = (*readChar)[0]; // 185
uint16_t b = (uint16_t) (*readChar)[0]; // 65465= b'1111 1111 1011 1001'
uint16_t c = (uint16_t) a; // 185= b'0000 0000 1011 1001'
printf("%u %u %u", a, b, c); // <====== this prints 185 65465 185
if (c==b) {
printf("YES\n");
} else {
printf("NO\n"); // <=== Always end up here
}
}