不使用 * 运算符进行强制转换

问题描述 投票:0回答:5

有人可以向我解释一下在这种情况下“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
c
5个回答
2
投票

在您的代码示例中,强制转换没有多大意义,因为

test1
已经是
unsigned long
,但当宏用于不同类型(如
unsigned char
等)时,它就有意义了。

您还应该在

%lu
中使用
printf
来打印
unsigned long

printf("(unsigned long)test1 = %lu\n", (unsigned long)(test1));
//                              ^^

1
投票

它把它加宽到

unsigned long
的大小。想象一下,如果您使用
char
调用此函数并将其右移 8 位,则与操作的工作方式将不同。

也只是发现了这个(查看右移运算符)为什么它是无符号的。显然,无符号强制进行逻辑移位,其中每个移位位置的最左边的位都被零替换。而有符号值移位则执行算术移位,其中最左边的位被删除的最右边的位替换。

示例:

11000011 ( unsigned, shifted to the right by 1 )
01100001

11000011 ( signed, shifted to the right by 1 )
11100001

1
投票

有人可以向我解释一下在这种情况下“n”发生了什么吗?

您正在将

n
投射到
unsigned long

那么 (unsigned long)(n) 实际上做了什么?

它将把

n
提升为
unsigned long


0
投票

转换输入是在位移位和与操作之前所做的全部事情。请注意 if 运算的顺序和运算符的优先级。这是相当难看的。

但是看起来他们是在避免碰到符号位,并且通过这样做而不是函数,就没有对 n 进行类型检查。

它只是丑陋。

更好的形式是拥有一个具有输入类型检查功能的干净清晰的函数。


0
投票

这确保了

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:

© www.soinside.com 2019 - 2024. All rights reserved.