1 是一个整数常量,类型 int 。表达方式 1 << current_bit 也有类型 int ,但对于16位 int ,表达式的结果是未定义的 current_bit 大于14.行为在您的情况下未定义,那么,您的调试器可能会显示与观察到的行为不一致的整体表达式的结果。如果你用过 unsigned int 不变的, 即 1u ,那么结果的temp值将被定义为0 current_bit 大于15,因为左移的结果将为零。
1
int
1 << current_bit
current_bit
unsigned int
1u
通过以足够宽的类型执行计算来保存结果来解决此问题。这是一个紧凑,正确,非常清晰的方法来纠正您的代码:
DS18B20_send_bit(pin, (path_table & (((uint64_t) 1) << current_bit)) != 0);
或者如果 path_table 有一个未签名的类型然后我更喜欢这个,虽然它更偏离你的原始:
path_table
DS18B20_send_bit(pin, (path_table >> current_bit) & 1);
这里实现#1是AVR是1980-1990的技术核心。早餐时不是用64位数字来咀嚼x64 PC,而是效率极低的8位MCU。因此:
在您做任何其他事情之前,您需要摆脱所有64位算术并从根本上最小化32位算术的使用。期。应该没有单个变量 uint64_t 在你的代码中,或者你做得非常错误。
uint64_t
有了这个启示,所有8位MCU总是有一个 int 类型是16位。
在代码中 1<<current_bit ,整数常量 1 是类型的 int 。意思是如果 current_bit 是15或更大,您将位移到此临时的符号位 int 。这总是一个错误。严格来说,这是未定义的行为。在实践中,您可能最终会随机更改数字符号。
1<<current_bit
为避免这种情况,请勿在带符号数字上使用任何形式的按位运算符。当混合整数常数时如 1 使用按位运算符,将它们更改为 1u 避免像上面提到的那样的bug。
如果有人知道从变量中提取单个位的更有效/紧凑的方法,我真的很感激,如果你可以分享
C中最有效的方法是: uint8_t variable; ... if(variable & (1u << bits)) 。这应转换为相关的“分支(如果位设置”)指令。
uint8_t variable; ... if(variable & (1u << bits))
我的一般建议是找到你的工具链的反汇编程序,看看C代码实际生成的机器代码。你不必是一个汇编大师来阅读它,偷看它 指令系统 应该够了。