我在这里遇到了一个小问题。我有一个unsigned char数组,我试图访问字节2-3(0xFF
和0xFF
)并将其值作为简短值。
代码:
unsigned char Temp[512] = {0x00,0xFF,0xFF,0x00};
short val = (short)*((unsigned char*)Temp+1)
虽然我希望val包含0xFFFF
,但它实际上包含0x00FF
。我做错了什么?
答案 0 :(得分:7)
当数据未正确对齐时,无法保证您可以访问short
。
在某些计算机上,特别是RISC计算机上,您会因未对齐访问而出现总线错误和核心转储。在其他机器上,未对齐的访问将涉及到内核的陷阱以修复错误 - 这比核心转储快一点。
为了可靠地获得结果,你最好做转移和/或:
val = *(Temp+1) << 8 | *(Temp+2);
或:
val = *(Temp+2) << 8 | *(Temp+1);
请注意,这明确提供了数据的big-endian(第一选项)或little-endian(第二)解释。
另请注意谨慎使用<<
和|
;如果您使用+
而不是|
,则必须使用shift表达式括号或使用乘法而不是shift:
val = (*(Temp+1) << 8) + *(Temp+2);
val = *(Temp+1) * 256 + *(Temp+2);
合乎逻辑并使用逻辑或算术,而不是混合。
答案 1 :(得分:6)
当您应该解除unsigned char*
short*
我认为这应该有效:
short val = *((short*)(Temp+1))
答案 2 :(得分:4)
您的问题是您只访问数组的一个字节:
*((unsigned char*)Temp+1)
会取消引用Temp+1
的指针0xFF
(short)*((unsigned char*)Temp+1)
会将取消引用的结果转换为short
。将unsigned char
0xFF
简化为简短显然会为您提供0x00FF
所以你要做的是*((short*)(Temp+1))
但是应该注意到你正在做的是一个可怕的黑客。首先,当你有不同的chars
时,结果显然取决于机器的字节顺序。
其次,无法保证所访问的数据被正确对齐以便作为简短的访问。
因此,根据您的架构的字节顺序执行short val= *(Temp+1)<<8 | *(Temp+2)
或short val= *(Temp+2)<<8 | *(Temp+1)
这样的操作可能更好一点
答案 3 :(得分:1)
我不推荐这种方法,因为它是特定于体系结构的。
考虑Temp
的以下定义:
unsigned char Temp[512] = {0x00,0xFF,0x88,0x00};
根据系统的字节顺序,您会得到Temp + 1
到short *
的不同结果;在一个小端系统上,结果将是值0x88FF
,但在Big endian系统上,结果将是0xFF88
。
此外,我认为这是一个未定义的演员,因为对齐问题。
你可以使用的是:
short val = (((short)Temp[1]) << 8) | Temp[2];