C中的整数除法与无符号短整数

Ste*_*nik 1 c arrays integer division

我觉得这是最血腥的初学者 - 为什么以下不起作用:

// 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
Run Code Online (Sandbox Code Playgroud)

在printf和我的调试器的监视列表中,addr [1]的值不是预期的.我的目标是获得变量的最大值的一半,这里是0x8000.信息:我正在做〜currentAddr以获得最大值.0xFFFF,如果我的嵌入式平台上的短路长度与我的PC上的长度不同.

欢呼,斯特凡

ex *_*ilo 6

什么地方出了错

整数提升是在一元的操作数上执行的~.

在许多系统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 <stdio.h>
#include <limits.h>

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;
}
Run Code Online (Sandbox Code Playgroud)

节目输出:

(USHRT_MAX / 2) + 1: 0x8000
     USHRT_MAX >> 1: 0x7fff
Run Code Online (Sandbox Code Playgroud)