我在C:
中有这个案例陈述case GOTO: {
int o1 = (int)P[pc+1];
unsigned int o2 = (unsigned)P[pc+2];
int offset =(o1<<8) | o2;
pc = pc + (int)offset;
break;
}
现在关于代码:
P[pc+x]
将提供1
字节整数。
基本上,在此结束时,我想将pc
设置为已签名的4
字节int
。然而,它并没有这样做。它正在做的是取1
字节,将其移位,然后取第二个字节然后按位,或简单地添加它。它没有考虑o1的符号。因此,如果P[pc+1] = FF
和P[pc+2] = E1
,正在发生的事情是offset = 0000FFE1
。但我想要的是offset = FFFFFFE1
。基本上,第一个2
字节应采用P[pc+1]
的符号。但这不会发生。我做错了什么?
答案 0 :(得分:1)
如果这对您有意义,请检查一下: #include
int main(void) {
short pc1= 0xFF;
short pc2= 0xE1;
int pc = 0;
unsigned int highbits = 0xFFFFFFFF;
// Check for sign bit, if true OR with highbits
// to set all remaining bits to high
int o1 = pc1 & 0xF0 ? pc1 | highbits : pc1;
int offset = (int)( (o1<<8) | pc2 );
pc = pc + (int)offset;
printf("\npc1=%x pc2=%x pc=%x", pc1, pc2, pc);
printf("\n");
return 0;
}
输出:
pc1=ff pc2=e1 pc=ffffffe1
答案 1 :(得分:1)
我没有看到P的声明,但是当你说它是一个字节数组时,我假设它具有的特定类型是unsigned char。
如果它被签名,则转换将按照您想要的方式运行,因为,例如,-1 char将变为-1 int,符号位移位,其余位根据需要反转。但是当你从unsigned char转换为signed int时,结果将始终是一个正int。
因此,要解决这个问题,一种方法是在解除引用之前强制转换指针/数组,它会给出所需的结果:
int o1 = (int)(((char *)P)[pc+1]);
另一件事:位移不能很好地使用有符号值,因为它只会移走符号位。它可以在你的例子中工作,因为你有0xFF,但是如果你有0x80,那么它将是0x80000000作为int,并且在移位后变为0x00000000。
因此,不是8位移位,而是进行乘法运算:
int offset =(int)( (o1 * 256) + o2 );
答案 2 :(得分:0)
你应该检查你的编译器如何在C中执行Unsigned-signed和反之的castings。 如果我没记错的话(抱歉,如果我错了),一旦你在A = B(其中A接收B的值)这样的操作中至少有一个UNSIGNED变量,编译器就会将这两个值作为UNSIGNED值处理。
这可能会弄乱您的代码。 让我以这种或那种方式知道答案,如果我弄清楚为什么会发生这种情况,我会在这里发表评论