显式铸造问题,C

时间:2011-12-04 22:18:21

标签: c casting unsigned signed

我在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] = FFP[pc+2] = E1,正在发生的事情是offset = 0000FFE1。但我想要的是offset = FFFFFFE1。基本上,第一个2字节应采用P[pc+1]的符号。但这不会发生。我做错了什么?

3 个答案:

答案 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值处理。

这可能会弄乱您的代码。 让我以这种或那种方式知道答案,如果我弄清楚为什么会发生这种情况,我会在这里发表评论