有人可以向我解释一下在这种情况下“n”发生了什么吗?
main.c
unsigned long temp0;
PLLSYS0_FWD_DIV_A_DECODE(n);
main.h
#define PLLSYS0_FWD_DIV_A_DECODE(n) ((((unsigned long)(n))>>8)& 0x0000000f)
我知道 n 被移位 8 位,然后与 0x0000000f 进行与运算。那么 (unsigned long)(n) 实际上做了什么?
#include <stdio.h>
int main(void)
{
unsigned long test1 = 1;
printf("test1 = %d \n", test1);
printf("(unsigned long)test1 = %d \n", (unsigned long)(test1));
return 0;
}
输出:
test1 = 1
(unsigned long)test1 = 1
在您的代码示例中,强制转换没有多大意义,因为
test1
已经是 unsigned long
,但当宏用于不同类型(如 unsigned char
等)时,它就有意义了。
您还应该在
%lu
中使用 printf
来打印 unsigned long
。
printf("(unsigned long)test1 = %lu\n", (unsigned long)(test1));
// ^^
它把它加宽到
unsigned long
的大小。想象一下,如果您使用 char
调用此函数并将其右移 8 位,则与操作的工作方式将不同。
也只是发现了这个(查看右移运算符)为什么它是无符号的。显然,无符号强制进行逻辑移位,其中每个移位位置的最左边的位都被零替换。而有符号值移位则执行算术移位,其中最左边的位被删除的最右边的位替换。
示例:
11000011 ( unsigned, shifted to the right by 1 )
01100001
11000011 ( signed, shifted to the right by 1 )
11100001
有人可以向我解释一下在这种情况下“n”发生了什么吗?
您正在将
n
投射到 unsigned long
。
那么 (unsigned long)(n) 实际上做了什么?
它将把
n
提升为unsigned long
。
转换输入是在位移位和与操作之前所做的全部事情。请注意 if 运算的顺序和运算符的优先级。这是相当难看的。
但是看起来他们是在避免碰到符号位,并且通过这样做而不是函数,就没有对 n 进行类型检查。
它只是丑陋。
更好的形式是拥有一个具有输入类型检查功能的干净清晰的函数。
这确保了
n
具有适当的大小(以位为单位),最重要的是被视为无符号。由于移位运算符执行符号扩展,因此当数字带符号且为负数时,扩展将以 1 而不是 0 进行。这意味着负数移位将始终导致负数。
例如:
int main()
{
long i = -1;
long x, y;
x = ((unsigned long)i) >> 8;
y = i >> 8;
printf("%ld %ld\n", x, y);
}
在我的机器上输出:
72057594037927935 -1
由于
y
中的符号扩展,数字仍然是-1: