高分求解一个绝对有难度的问题!!!

houdaping 2007-10-19 02:33:53
有一个数组 const unsigned char c[] = {数组元素这里不写出来了,因为很大,等下会给出需要的元素值};
已知
int i = 49;
char[i] = 0x81;
char[i+1] = 0x00;
char[i+2] = 0x6c;
现在执行下面的语句
unsigned int addr=(c[i+1]<<8)|c[i+2];
printf("addr = %08x \n",addr);

问题出现来了!
我在little机(这里在个人电脑上的vc平台上编译的)上打印出的c[i+1] = 0x00;c[i+2]= 0x6c; addr的值为0x0000006c;
然后我移植到big机(在自己的芯片编译)上时c[i+1] = 0x00;c[i+2] = 0x6c 打印出的addr的值为0x8047e8d0;

如果手动计算的话 值应该是0x0000006c; 但是为什么会出现addr的值为0x8047e8d0的这种情况(照理说就算是字节高低位顺序相反,也不可能差别这么大啊!).
请高手帮忙分析下出现的原因.
...全文
623 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
gao_fei 2007-10-22
  • 打赏
  • 举报
回复
看不懂,学习中
jayskycai 2007-10-22
  • 打赏
  • 举报
回复
觉得lz在玩我们! 难道他的计算机已经只能化了
gs0038 2007-10-21
  • 打赏
  • 举报
回复
看不懂,不知道这方面的知识在哪里找得到,各个说一下好吗
yibutonghua 2007-10-21
  • 打赏
  • 举报
回复
在c中,所有的位移操作的右操作数必须小于左操作数的位长度.
  否则会出现溢出的可能,导致结果出错.
  
blue_zyb 2007-10-20
  • 打赏
  • 举报
回复
对于ls的问题,谈一点个人的想法:

首先,80386 instruction set是底层实现,而C语言作为一种高级语言实现,并不需要与底层细节一一对应。况且,x86也只是一种典型的architecture,所以还有其他的处理器结构实现,并不一定支持当个char数据类型的操作。据我所知,好像power pc的寄存器(假设为32位实现)就只有r0,r1。。。,而不支持像x86一样,访问单个寄存器中的byte部分。(即80386可以访问eax中的al部分)。

另外,从语言抽象的角度来说。我认为C语言引入char,short等数据类型主要是基于节约存储的考虑,但本质上它们属于整数类型,代表了数字。所以在进行加减以及移位等“针对整数”的操作时,统一将其提升为符合机器字长的int类型进行运算。因为比如有操作:
unsigned char x = 255;
unsigned int y = x + 1;
那么我们更期望得到的结果是y = 256,而不是对8 bit的x进行加1操作,得导致溢出得到的0。移位操作可能亦是如此。
loops 2007-10-20
  • 打赏
  • 举报
回复
我还不太明白的地方是,明明80386的shl和shr是支持8位的位移,为啥在C里面,就要对char搞“integral promotion”呢?
这么以来,对于int和char,至少CF的值可能会不一样。
参考下面网址的资料:
http://pdos.csail.mit.edu/6.828/2007/readings/i386/SAL.htm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Opcode Instruction Clocks Description
D0 /4 SAL r/m8,1 3/7 Multiply r/m byte by 2, once

The shift is repeated the number of times indicated by the second operand, which is either an immediate number or the contents of the CL register. To reduce the maximum execution time, the 80386 does not allow shift counts greater than 31. If a shift count greater than 31 is attempted, only the bottom five bits of the shift count are used. (The 8086 uses all eight bits of the shift count.)

blue_zyb 2007-10-19
  • 打赏
  • 举报
回复
to loops:
我记得所有的位移操作的右操作数必须小于左操作数的位长度,否则结果未定义。可能是各个CPU对这个实现不一样。
-----------------------------------------------------------
你记得没有错,不过你忽视了的一点是:对于移位操作符,将对它的左操作数进行integral promotion,也就是,这里会将char类型向上提升为int类型,而int的为长度为32,8显然比只要小

所以这个考虑是没有根据的。其实lz不是已经对他自己的问题给出了解答么,说是什么“分配完空间的时候,就开始操作,就会出现乱码”,奇怪的系统。。。

当然,我上面说的也是依据标准来的,可能lz的怪系统有其他的解释方式也说不定,哈哈。
gs0038 2007-10-19
  • 打赏
  • 举报
回复
郁闷中
lsg78557768 2007-10-19
  • 打赏
  • 举报
回复
学习中~~
loops 2007-10-19
  • 打赏
  • 举报
回复
unsigned int addr=(c[i+1] < <8) ¦c[i+2];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我记得所有的位移操作的右操作数必须小于左操作数的位长度,否则结果未定义。可能是各个CPU对这个实现不一样。
改成这个试试,会不会有问题:unsigned int addr=( ((unsigned int)c[i+1]) <<8 ) ¦c[i+2];
Arthur_ 2007-10-19
  • 打赏
  • 举报
回复
严格说没初始化的时候 系统应该默认值为0; //这句话纯属扯淡。
会思考的草 2007-10-19
  • 打赏
  • 举报
回复
严格说没初始化的时候 系统应该默认值为0; //这句话纯属扯淡。
blue_zyb 2007-10-19
  • 打赏
  • 举报
回复
乱码,还有这种事情。。。
lz的是什么系统阿,好有趣。。。
houdaping 2007-10-19
  • 打赏
  • 举报
回复
等了1-2分钟 在回过去打印,结果又正常了!!!!!!!
有人说是还没分配完空间的时候,就开始操作,就会出现乱码!!!
不过 还是不能肯定是什么原因!!~!

比如说我定义一个unsigned int i; 马上执行printf("i=%x\n",i);结果还是会出现0x87024e14;严格说没初始化的时候 系统应该默认值为0;

听不听话 2007-10-19
  • 打赏
  • 举报
回复
建议搂住这样试一下:
unsigned int addr=(c[i+1] < <8) ¦c[i+2]);
改为:
char temp1=c[i+1];
char temp2=c[i+2];
unsigned int ci1=(unsigned int)temp1;
unsigned int ci2=(unsigned int)temp2;
unsigned int addr=(ci1 < <8) ¦ci2);
之所以这样试,因为我感觉是就是不同硬件(或编译系统)对内存的操作(包括类型强制转换)有区别.所以可能造成上述现象.


同意4楼的看法。
blue_zyb 2007-10-19
  • 打赏
  • 举报
回复
ls有点扯淡了吧。。。
c[i+1] == 0x0,再怎么强转也是0,所以实际上就是unsigned int addr = c[i+2];
怎么也不可能出现0x8047e8d0这个值,我反而觉得这个值有点像变量的地址。
_石头_ 2007-10-19
  • 打赏
  • 举报
回复
建议搂住这样试一下:
unsigned int addr=(c[i+1] < <8) ¦c[i+2]);
改为:
char temp1=c[i+1];
char temp2=c[i+2];
unsigned int ci1=(unsigned int)temp1;
unsigned int ci2=(unsigned int)temp2;
unsigned int addr=(ci1 < <8) ¦ci2);
之所以这样试,因为我感觉是就是不同硬件(或编译系统)对内存的操作(包括类型强制转换)有区别.所以可能造成上述现象.
shu_yoyo 2007-10-19
  • 打赏
  • 举报
回复
char[i] = 0x81;
char[i+1] = 0x00;
char[i+2] = 0x6c;
这个是什么啊?
会思考的草 2007-10-19
  • 打赏
  • 举报
回复
什么芯片?big endian和little endian的原因?
blue_zyb 2007-10-19
  • 打赏
  • 举报
回复
估计是你的目标机器环境有点问题吧。。。

因为第一直觉这几行代码的结果与大小端无关,结果是一样的
其次在power pc机器上(big endian)作了测验,输出的结果是0x0000006c.

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧