我写了一小段代码,我有点不确定这里是否正确实现了符号扩展
本质上
我有一个
char*
数据数组,其中包含以字节为单位的值
现在我想从这个数据数组构造一个 16 位(2 字节)的值
我通过获取字节 @ 地址 0 和地址 1 并将它们组合起来来做到这一点。
这部分正在工作,我确信它
现在这是一个 16 位值,我打算将其存储在我的有符号整数数组中。显然整数是 32 位(4 字节)因此需要用额外的 16 位填充
现在我的问题是这个
void store_data(unsigned char* data){
int param1 = 5;
int param2 = 6;
int address = array_of_ints[param2] + 50;
int value = memory[address] | (memory[address+1] << 8);
int32_t sign = value;
array_of_ints[param1] = sign;
}
我的代码是否正确地从内存中扩展了值
因为我将它存储为带符号的 32_int,所以我不需要用额外的 16 位填充它,对吗?
你的答案取决于 memory 是如何定义的。你建议,在文中,它是一个
array of char
;字符通常(但不是明确地)签名,所以不,你的代码会有一些奇怪的值。
那应该比较容易测试;把值像 { 0, 1, 0x7f, 0x80, 0x81 };在内存中的某些位置,观察打印变量的输出。
一个微妙的问题是您的 shift 和 or 生成 16 位值。你的表情:
memory[address] | (memory[address+1] << 8)
by type 看起来像(signed char) | (signed int)
。你想要的是(unsigned char) | (unsigned short)
。最重要的是你必须抑制内存 [] 中的符号扩展。你可能希望它是未签名的。
与假设 int 或 short 大小相比,使用
你想多了。一般来说,不需要对符号扩展做特殊规定。它自动发生。 只要分配的值可以在目标左值的类型中表示,C 中的分配就是保值的。
所以,如果您的
int
只有 16 位宽,或者如果您的 memory
有符号类型,那么您已经有问题了
memory[address+1] << 8
(子)表达式
memory[address+1]
被提升为类型 int
用于操作,并且结果已经具有类型 int
。如果你有任何问题,那么它们会在这个表达式的计算中体现出来。
取名
array_of_ints
来准确表示所涉及的类型,您可以直接将|
表达式赋值给数组元素,而无需引入任何临时变量:
array_of_ints[param1] = memory[address] | (memory[address+1] << 8);
临时工不会为你做任何有用的事情。
因为我将它存储为带符号的 32_int,所以我不需要用额外的 16 位填充它,对吗?
你认为你会如何手动填充结果?也许您对按位运算的性质感到困惑。这些是对 values 的操作,而不是(直接)对对象 representations 的操作。其中的含义是你是正确的:如果你已经执行的计算首先被明确定义,那么你不需要采取任何额外的步骤来获得用零填充的最高有效位。