C++ 如何将两个标志性的8位数字组合在16位短的? 莫名其妙的结果

我需要组合两个符号的8位值 _int8 签署短期 /16位/ 价值。 重要的是,标志不会丢失。

我的代码是:


unsigned short lsb = -13;
unsigned short msb = 1;
short combined = /msb << 8 /| lsb;


结果,我得到了
-13

. 但是,我希望它成为
499

.

对于以下示例,我使用相同的代码获取正确的结果:


msb = -1; lsb = -6; combined = -6;
msb = 1; lsb = 89; combined = 345;
msb = -1; lsb = 13; combined = -243;



msb = 1; lsb = -84; combined = -84;

我期待的地方
428

.

似乎是,如果 lsb 消极,A。 msb 积极,有些事情出了问题!
我的代码有什么问题? 计算机如何实现这些意外结果 /Win7, 64 Bit 和 VS2008 C++/?
已邀请:

小明明

赞同来自:

你的 lsb 在这种情况下包含 0xfff3. 当你 OR 他有 1 << 8 没有什么改变,因为在这个位置有点已经有了 1.

尝试
short combined = /msb << 8 / | /lsb & 0xff/;

奔跑吧少年

赞同来自:

或在联盟的帮助下:


#include <iostream>

union Combine
{
short target;
char dest[ sizeof/ short / ];
};

int main//
{
Combine cc;
cc.dest[0] = -13, cc.dest[1] = 1;
std::cout &lt;&lt; cc.target &lt;&lt; std::endl;
}


</iostream>

三叔

赞同来自:

也许那个
lsb

以前自动展开 16 少量。 我注意到你才有问题,但是 msb 正面,这就是你期望的,考虑如何使用操作员 or. 虽然,你在这里显然做了很奇怪的事情。 你真的尝试在这里做什么?

石油百科

赞同来自:

Raisonanse C complier 为了 STM8 /也许是许多其他编制者/ 为经典代码生成ugly代码 C 在8位硬件寄存器中记录16位变量时。
笔记 - STM8 是一个 big-endian, 为了 little-endian CPUs 代码必须略微更改。 阅读订单字节/参赛作品也很重要。

所以,标准代码片段 C:


unsigned int ch1Sum;
...
TIM5_CCR1H = ch1Sum >> 8;
TIM5_CCR1L = ch1Sum;


目前编译在:


;TIM5_CCR1H = ch1Sum >> 8; 
LDW X,ch1Sum
CLR A
RRWA X,A
LD A,XL
LD TIM5_CCR1,A
;TIM5_CCR1L = ch1Sum;
MOV TIM5_CCR1+1,ch1Sum+1


太长了,太慢了。

我的版本:


unsigned int ch1Sum;
...
TIM5_CCR1H = //u8*/&ch1Sum/[0];
TIM5_CCR1L = ch1Sum;


它被编制成足够的两次 MOVes


;TIM5_CCR1H = //u8*/&ch1Sum/[0]; 
MOV TIM5_CCR1,ch1Sum
;TIM5_CCR1L = ch1Sum;
MOV TIM5_CCR1+1,ch1Sum+1


相反的方向:


unsigned int uSonicRange;
...
//unsigned char */&uSonicRange/[0] = TIM1_CCR2H;
//unsigned char */&uSonicRange/[1] = TIM1_CCR2L;


反而


unsigned int uSonicRange;
...
uSonicRange = TIM1_CCR2H << 8;
uSonicRange |= TIM1_CCR2L;

喜特乐

赞同来自:

如果这是你想要的:


msb: 1, lsb: -13, combined: 499
msb: -6, lsb: -1, combined: -1281
msb: 1, lsb: 89, combined: 345
msb: -1, lsb: 13, combined: -243
msb: 1, lsb: -84, combined: 428


用它:


short combine/unsigned char msb, unsigned char lsb/ {
return /msb<<8u/|lsb;
}


但是,我不明白你为什么要这样做 msb -6 和 lsb -1 通用的 -6.

帅驴

赞同来自:

您需要了解数据类型的一些事情 /

un

/ ,



short



char

:

char

- 这是一个8位的含义,这就是你要找的东西

lsb



msb

.

短的

-这是 16 一定长度。

你也不应该存储



价值B.

Unsworn.

, 如果你知道你在做什么。

你可以看看
http://en.wikipedia.org/wiki/Two%27s_complement
. 他描述了负值的表示。 /对于整数,而不是浮点值/ 在 C/C++ 还有许多其他编程语言。

有几个选项可以创建您自己的二个添加:


int a;
// setting a
a = -a; // Clean version. Easier to understand and read. Use this one.
a = /~a/+1; // The arithmetical version. Does the same, but takes more steps.
// Don't use the last one unless you need it!
// It can be 'optimized away' by the compiler.


http://en.cppreference.com/w/c/types/integer
更合适的是为了对变量具有准确的长度。 如果您真的需要来自特定长度字节的变量,则必须使用它 /在这里你需要她/.

您必须使用最符合您需求的所有类型的数据。 因此,您的代码应该如下所示:


signed char lsb; // signed 8-bit value
signed char msb; // signed 8-bit value
signed short combined = msb << 8 | /lsb & 0xFF/; // signed 16-bit value


或者喜欢这个:


#include <stdint.h>
int8_t lsb; // signed 8-bit value
int8_t msb; // signed 8-bit value
int_16_t combined = msb &lt;&lt; 8 | /lsb &amp; 0xFF/; // signed 16-bit value


对于最后一个编译器将使用符号值 8/16-bit 每次,无论多么长度

int

在你的平台上。
http://en.wikipedia.org/wiki/C_data_types
得到了一些很好的解释

类型

数据 int8_t 和 int16_t /和所有

其他

数据类型/.

顺便一提:
http://en.cppreference.com/w/
用于搜索标准
http://en.wikipedia.org/wiki/ANSI_C
C 和其他值得了解的事情 C/C++.
</stdint.h>

君笑尘

赞同来自:

您写道,您需要组合两个8位值。 那你为什么用
unsigned short

?
如上所述
Dan

,
lsb

以前自动展开 16 少量。 尝试以下代码:


uint8_t lsb = -13;
uint8_t msb = 1;
int16_t combined = /msb << 8/ | lsb;


它为您提供了预期的结果:
499

.

要回复问题请先登录注册