基于 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 位的)这样您就更接近您的目标架构并且您会更早发现类似问题。
strtol
returns一个long int
。如果 long int
在您的平台上是 32 位宽,那么它不能表示 0xffffffff
(大约 40 亿)。
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
。
这个程序接受命令行参数并填充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
.
根据编译器的不同,负数的移位可能会有所不同,如所述
这可能就是您遇到问题的原因:编辑:我对 可能 的看法是正确的 :),在 melponeme 评论之后,我刚刚测试了 strtol("0xffffffff)
的结果一个 32 位编译器,它 returns 0x7FFFFFFF
,所以问题不在于移位。
我敢肯定会解决你的问题的是,切换到 strtoul
到 return unsigned long 将达到目的:它将 return 一个 unsigned long (第一个问题已解决),并且可以确保换档会如您所愿。
最后一点,我建议您在 Linux 机器上使用 32 位编译器(即使机器是 64 位的)这样您就更接近您的目标架构并且您会更早发现类似问题。
strtol
returns一个long int
。如果 long int
在您的平台上是 32 位宽,那么它不能表示 0xffffffff
(大约 40 亿)。
The
strtol()
function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs,strtol()
returnsLONG_MIN
. If an overflow occurs,strtol()
returnsLONG_MAX
.
所以它returnsLONG_MAX
,在32位中是0x7fffffff
(或大约20亿),因为这是最大的正32位数字。
推测您的 Linux PC 使用 64 位 long int
,因此不会出现此问题。
要解决此问题,请将代码更改为使用 strtoul
,因为 0xffffffff
正好适合 unsigned long int
。