Jed*_*olf 1 c casting bit-manipulation type-conversion
我有一些C代码的变量为int,或在一段时间内转换为int以便于使用(我们关心的是位值)。在这种情况下,Int始终为32位。一方面,它们中的一些被分配给一个64位变量,其中一些被隐式分配,而某些被显式分配:
long long 64bitfoo = 32bitbar;
long long 64bitfoo = (long long)32bitbar;
Run Code Online (Sandbox Code Playgroud)
过去这不是问题,但是最近我遇到了这样一种情况:在此转换之后,64位变量的前32位不为0。似乎某些特定版本的事件可以或多或少地填充前几位与垃圾(或只是选择一个以前使用的内存位置,而不能正确清除它)。这不会,所以我正在寻找解决方案。
我可以很像这样做:
long long 64bitfoo = 32bitbar;
64bitfoo &= ~0xFFFFFFFF00000000;
Run Code Online (Sandbox Code Playgroud)
清除最重要的部分,这应该可以满足我的需求,但是我觉得有更好的选择。到目前为止,这仅在使用隐式强制转换的值上显示出来,所以我很好奇在隐式和显式强制转换之间是否存在允许显式强制转换本身处理的区别?(不幸的是,我目前不能只添加显式强制转换并进行测试,则触发该条件的条件很复杂且不容易复制,因此代码更改必须非常牢固,不能猜测)。
我确定可能还有其他选择,而不是仅仅使用=来设置值,或者以其他方式清除更好的前32位,或者通过某种方式设置初始64位值以确保如果仅设置了最低位,则最高位保持清零(有时会为64位变量分配其他64位变量,因此不能始终将最高位强制设置为0)。搜索时找不到很多东西,这似乎没什么用。
编辑:我忘了提到在某些情况下似乎没有签名的实例。一个示例是初始值是0xF8452370,然后long long值显示为-558965697074093200,即0xF83E27A8F8452370。因此,最低的32位是相同的,但是最高的32位不仅是1,而且是1和0的分散。据我了解,没有理由对有符号的签名和无符号的签名进行签名(全1),但是我肯定会弄错。
此外,我认为需要对64位变量进行签名,因为在其他情况下,它需要采用负或正(实际整数)的值,而在这些情况下,它只需要跟踪位值即可。这是一个非常多用途的变量,我没有能力使其不能多次使用。
edit2:很有可能我在这里问了一个错误的问题,试图引起注意。但是我在限制范围内工作,所以实际的问题可能是其他问题,并且暂时可能我只是被添加了创可贴。快速的总结是这样的:
有一个64位变量很长(或者在某些系统上是__int64,但是在我遇到的实例中,它应该总是很长)。我无法更改它的名称,也不能使其未签名。
我有一个返回32位内存地址的函数。我需要将该32位内存地址(不是指针,而是内存位置的实际值)分配给此64位变量。
在这些情况下,我需要64位变量的高32位为0,低32位与原始值相同。有时它们不是0,但并不总是1。
因为我无法将64位变量更改为unsigned,所以我认为最好的选择是手动清除前32位,并正在寻找实现此目的的最佳方法。
您正在遇到符号扩展-将负符号值强制转换为较大的类型将会将原始值的符号位“扩展”到新类型的所有高位,以便保留数字值。例如,(int8_t) 0xFC = -4转换为(int16_t) 0xFFFC = -4。多余的位不是“垃圾”;它们具有非常特定的目的和意义。
如果要避免这种情况,请强制转换为无符号类型。例如:
long long sixtyfourbits = (unsigned int) thirtytwobits;
Run Code Online (Sandbox Code Playgroud)
另外,我建议您<stdint.h>在代码中使用整数类型(如果您关心它们的大小),例如,使用int64_t代替long long和uint32_t代替unsigned int。名称将更清楚地表明您的意图,并且某些平台对标准C类型使用不同的大小。(例如,AVR微控制器使用16位int。)