作者:蔡少暖_171 | 来源:互联网 | 2023-01-06 21:36
我觉得这是最血腥的初学者 - 为什么以下不起作用:
// declarations
unsigned short currentAddr= 0x0000;
unsigned short addr[20] = {1, 0};
// main
addr[1] = (~currentAddr)/2+1;
printf("addr[1] wert: %hu\n", addr[1]); // equals 1, expecte 0x8000
addr[1] = ~currentAddr>>1;
printf("addr[1] wert: %hu\n", addr[1]); // equals 65535, expected 0x7FFF
在printf和我的调试器的监视列表中,addr [1]的值不是预期的.我的目标是获得变量的最大值的一半,这里是0x8000.信息:我正在做〜currentAddr以获得最大值.0xFFFF,如果我的嵌入式平台上的短路长度与我的PC上的长度不同.
欢呼,斯特凡
1> ex nihilo..:
什么地方出了错
整数提升是在一元的操作数上执行的~
.
在许多系统int
上大于short
.在这样的系统上,for unsigned short currentAddr = 0
,currentAddr
首先int
在表达式中提升值~currentAddr
.然后~currentAddr
评估为-1
(假设二进制补码表示).
在某些系统上int
,short
可能大小相同(但int
必须至少与大小一样大short
); 这里currentAddr
将被提升为,unsigned int
因为int
无法保存unsigned
相同大小的整数类型的所有值.在这种情况下,~currentAddr
会评估UINT_MAX
.对于16位int
(short
必须至少为16位,所以这里int
并且short
将是相同的大小),结果~currentAddr
将是65,535.
OP的系统必须int
大于short
.在的情况下,addr[1] = (~currentAddr)/2+1;
这成为addr[1] = (-1)/2+1;
其计算结果为1
.
在第二种情况下,addr[1] = ~currentAddr>>1;
评估为addr[1] = (-1)>>1;
.这里,右移右值的结果是实现定义的.在本例中,结果似乎是INT_MAX
,unsigned short
在转移中转换为转换中addr[1]
的值USHRT_MAX
.OP的系统上该值为65,535.
怎么办呢
要清楚可靠地获取标准整数类型的最大值和最小值,请使用找到的宏limits.h
而不是尝试位操作.这种方法不会令人失望:
#include
#include
int main(void)
{
unsigned short val;
val = (USHRT_MAX / 2) + 1;
printf("(USHRT_MAX / 2) + 1: %#hx\n", val);
val = USHRT_MAX >> 1;
printf(" USHRT_MAX >> 1: %#hx\n", val);
return 0;
}
节目输出:
(USHRT_MAX / 2) + 1: 0x8000
USHRT_MAX >> 1: 0x7fff