代码:
unsigned char array_add[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
...
if ((*((uint32_t*)array_add)!=0)||(*((uint32_t*)array_add+1)!=0))
{
...
}
我想检查数组是否全为零。所以我自然而然地想要将一个数组的地址(也恰好是第一个成员的地址)转换为unsigned int 32类型,因此我只需要执行两次,因为它是64位,8字节阵列。问题是,它已成功编译,但程序每次都在这里崩溃。
我在8位微控制器cortex-M0上运行我的程序。
我有多难?
答案 0 :(得分:2)
从理论上说这可行,但在实践中有一件事你不考虑:对齐内存访问。
如果uint32_t
需要对齐的内存访问(例如,4个字节),则将unsigned char
的数组转换为uint32_t*
,该数组具有1个字节的对齐要求,会生成指向未对齐的指针数组uint32_t
。
不支持Cortex-M0处理器上的未对齐访问。任何尝试执行未对齐的内存访问操作都会导致HardFault异常。
在实践中,这只是危险且脆弱的代码,在某些情况下会调用未定义的行为,正如Olaf所指出的那样,并且更好地解释了here。
答案 1 :(得分:1)
要测试多个字节,因为一次代码可以使用memcmp()
。
这有多快取决于编译器,因为优化编译器可以简单地发出快速8字节(或2 4字节)比较的代码。在{8}处理器上,即使memcmp()
也可能不会太慢。分析代码有帮助。
注意微观优化,因为它们往往无法有效地使用编码器时间进行重大优化。
unsigned char array_add[8] = ...
const unsigned char array_zero[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
if (memcmp(array_zero, array_add, 8) == 0) ...
另一种方法使用union
。小心不要假设add.arr8[0]
是最重要或最不重要的字节。
union {
uint8_t array8[8];
uint64_t array64;
} add;
// below code will check all 8 of the add.array8[] is they are zero.
if (add.array64 == 0)
一般而言,专注于编写清晰的代码并为非常选择案例保留这些小优化。
答案 2 :(得分:-3)
我不确定但是如果你的数组有8个字节,那么只需将基地址分配给long long
变量并将其与0进行比较。这应该可以解决检查数组是否全为0的问题。
编辑1:在奥拉夫的评论之后,我会说用long long
替换int64_t
。但是,为什么不是一个简单的循环来迭代数组和检查。你需要比较8个字符。
编辑2:另一种方法可能是对所有数组元素进行OR运算,然后与0进行比较。如果全部为0,则OR将为零。我不知道CMP是快还是OR。有关精确的CPU周期要求,请参考Cortex-M0文档,但是,我希望CMP更慢。