了解我的代码是否处理符号扩展

问题描述 投票:0回答:2

我写了一小段代码,我有点不确定这里是否正确实现了符号扩展

本质上

我有一个

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 位填充它,对吗?

c bit-manipulation bit sign-extension
2个回答
0
投票

你的答案取决于 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 大小相比,使用 和相应的 (int8_t, uint8_t, int16_t, ..., uint64_t) 更可取。


0
投票

你想多了。一般来说,不需要对符号扩展做特殊规定。它自动发生。 只要分配的值可以在目标左值的类型中表示,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 的操作。其中的含义是你是正确的:如果你已经执行的计算首先被明确定义,那么你不需要采取任何额外的步骤来获得用零填充的最高有效位。

© www.soinside.com 2019 - 2024. All rights reserved.