我有一些C代码,这些变量要么是int,要么是为了便于使用而转换为int(我们关心的是位值)。在这种情况下,Int将始终是32位。其中一些被分配给64位变量,有些是隐式的,有些是显式的:
long long 64bitfoo = 32bitbar;
long long 64bitfoo = (long long)32bitbar;这在过去并不是一个问题,但是最近我遇到了一种情况,在这种转换之后,64位变量的前32位不是0。似乎某些特定版本的事件或多或少会用垃圾填充顶部的位(或者只是选择以前使用过的内存位置,而不是正确地清除它)。这是行不通的,所以我正在寻找解决方案。
我显然可以做这样的事:
long long 64bitfoo = 32bitbar;
64bitfoo &= ~0xFFFFFFFF00000000;清除顶部的部分,这应该适用于我所需要的,但我觉得有更好的选择。到目前为止,这只显示在使用隐式强制转换的值上,因此我很好奇,隐式和显式转换之间是否存在允许显式强制转换来处理这个问题的区别?(不幸的是,我目前不能仅仅添加显式强制转换并进行测试,触发这种转换的条件非常复杂,不易复制,因此代码更改需要非常坚定,而不是猜测)。
我确信还可能有其他选项,不只是使用=来设置值,使用不同的方式清除前32位(更好),或者以某种方式设置初始64位值(如果只设置底部位,则保证顶部位保持清晰)( 64位变量有时会得到分配给它的其他64位变量,因此不可能在任何时候都强制将顶位强制为0)。在搜索的时候并没有发现很多东西,这似乎并不是什么经常发生的事情。
编辑:我忘了提到,在某些情况下,签名似乎并不是问题所在。一个例子是初始值为0xF8452370,然后长值为-558965697074093200,即0xF83E27A8F8452370。所以,下面的32位是相同的,但前32位不只是1,而是1和0的零散。据我所知,没有理由用符号和无符号的方式来做这件事(这是肯定的),但我肯定会弄错。
此外,我认为需要对64位变量进行签名,就像在其他情况下,它接受的值需要是负数或正值(实际整数),而在这些情况下,它只需要跟踪位值。这是一个非常多用途的变量,我没有能力使它不是多用途。
edit2:我很可能在这里问错了问题,试图关注这个问题。但是我是在限制范围内工作的,所以实际的问题可能是其他的问题,而且我现在可能只是被困在加了一个绷带。最简单的问题是:
发布于 2017-11-28 18:47:45
您将遇到符号扩展--将负号值转换为更大的类型,将原始值的符号位“扩展”到新类型的所有上位,从而保留数字值。例如,(int8_t) 0xFC = -4转换为(int16_t) 0xFFFC = -4。额外的部分不是“垃圾”,它们有一个非常具体的目的和意义。
如果要避免这种情况,请使用无符号类型进行强制转换。例如:
long long sixtyfourbits = (unsigned int) thirtytwobits;另外,我建议您在代码中使用<stdint.h>整数类型,如果您关心它们的大小--例如,使用int64_t而不是long long,使用uint32_t代替unsigned int。名称将更清楚地表明您的意图,并且有一些平台对标准C类型使用不同的大小。(例如,AVR微控制器使用16位int。)
发布于 2017-11-28 19:05:37
我们关心的是比特值
然后,您应该远离签名的类型,并且始终使用无符号。
当有符号(或无符号)类型转换为同一类型的更大大小时,将保留值,即19变为19,-19变为-19。
但是有符号类型并不总是通过在前面添加零来保持二进制模式,当从较小的类型转到更大的类型时,而无符号类型则这样做。
对于2的补码(符号类型最常见的表示形式),所有负值将是符号扩展,这意味着在前面添加ones而不是0。
SIGNED:
8 bit: -3 -> FD
16 bit: -3 -> FFFD
32 bit: -3 -> FFFFFFFD
64 bit: -3 -> FFFFFFFFFFFFFFFD
UNSIGNED:
8 bit: 253 -> FD
16 bit: 253 -> 00FD
32 bit: 253 -> 000000FD
64 bit: 253 -> 00000000000000FD似乎某些特定版本的事件或多或少地会用垃圾填充顶部的位。
不,要么新的额外位将全部为零,要么它们都是1。
如果不是这样,您的系统就不符合C标准。
发布于 2020-09-16 00:35:49
“‘Union”是C语言中解决这个问题的自然方式。
typedef union {
struct {
int low; // low 32 bits
int high; // high 32 bits
} e; // 32bits mimic x86 CPU eax
__int64 r; // 64bits mimic x86 CPU rax
} Union64;
Union64 data;
data.r = 0x1122334455667788;然后data.e.high是0x11223344,data.e.low是0x55667788。
反之亦然
data.e.high = 0xaabbccdd;
data.e.low = 0x99eeff00;然后data.r将是0 xaabbccdd99eeff00。
在你的情况下
data.r = 0; // guarantee data.e.high is cleared
data.e.low = 32bitbar; // say 0x11223344则data.r为0x0000000011223344;
这正是工会的目的。
https://stackoverflow.com/questions/47538706
复制相似问题