基于 MIPS 的架构中的 C 程序错误

C program error in MIPS based architecture

这个程序接受命令行参数并填充write_key数组

#include <stdio.h>
#include <stdlib.h>

 int main(int argc, char **argv)
 {
   int i,j;
   unsigned char write_key[16];

   for(j=0;j<4;j++){
     for(i=0;i<4;i++){
       write_key[j*4 + i] = (strtol(argv[1+j],NULL,16)>>(8*(4-1-i))) & 0xff;
     }
   }

   for(i=0;i<16;i++){
     printf("write_key[%d] :: 0x%x   \n", i, writekey[i]);
   }
  printf("\n");
}

我用

启动程序
./app 0xffffffff 0xffffffff 0xffffffff 0xffffffff 

对于以下输入 我的 linux 电脑上的输出是

write_key[0] :: 0xff   
write_key[1] :: 0xff   
write_key[2] :: 0xff   
write_key[3] :: 0xff   
write_key[4] :: 0xff   
write_key[5] :: 0xff   
write_key[6] :: 0xff   
write_key[7] :: 0xff   
write_key[8] :: 0xff   
write_key[9] :: 0xff   
write_key[10] :: 0xff   
write_key[11] :: 0xff   
write_key[12] :: 0xff   
write_key[13] :: 0xff   
write_key[14] :: 0xff   
write_key[15] :: 0xff

符合预期。 但是当我为基于 Mips 的嵌入式板和 运行 交叉编译这个程序时,我的输出是。

write_key[0] :: 0x7f   
write_key[1] :: 0xff   
write_key[2] :: 0xff   
write_key[3] :: 0xff   
write_key[4] :: 0x7f   
write_key[5] :: 0xff   
write_key[6] :: 0xff   
write_key[7] :: 0xff   
write_key[8] :: 0x7f   
write_key[9] :: 0xff   
write_key[10] :: 0xff   
write_key[11] :: 0xff   
write_key[12] :: 0x7f   
write_key[13] :: 0xff   
write_key[14] :: 0xff   
write_key[15] :: 0xff 

为什么不同架构的输出不同?

strtol returns 一个长整数,可能是一个 32 位整数,有符号。它的范围从 -1 (0xFFFFFFFF) 到 0x7FFFFFFF.

根据编译器的不同,负数的移位可能会有所不同,如所述 and here(右移负数调用 C 中实现定义的行为)

这可能就是您遇到问题的原因:编辑:我对 可能 的看法是正确的 :),在 melponeme 评论之后,我刚刚测试了 strtol("0xffffffff) 的结果一个 32 位编译器,它 returns 0x7FFFFFFF,所以问题不在于移位。

我敢肯定会解决你的问题的是,切换到 strtoul 到 return unsigned long 将达到目的:它将 return 一个 unsigned long (第一个问题已解决),并且可以确保换档会如您所愿。

最后一点,我建议您在 Linux 机器上使用 32 位编译器(即使机器是 64 位的)这样您就更接近您的目标架构并且您会更早发现类似问题。

strtolreturns一个long int。如果 long int 在您的平台上是 32 位宽,那么它不能表示 0xffffffff(大约 40 亿)。

man strtol:

The strtol() function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX.

所以它returnsLONG_MAX,在32位中是0x7fffffff(或大约20亿),因为这是最大的正32位数字。

推测您的 Linux PC 使用 64 位 long int,因此不会出现此问题。

要解决此问题,请将代码更改为使用 strtoul,因为 0xffffffff 正好适合 unsigned long int