案例是我正在研究我在互联网上发现的引起我注意的代码,是这样的:
#include <stdio.h>
#include <stdint.h>
#define NEG ~0x0LL
void ITOC(int8_t *vec, int n)
{
int8_t *p = vec;
for(; n; n /= 10) *p++ = n % 10;
}
void ncmp(int8_t *buf, int y)
{
int tmp, i = 0;
for (; y ; y/=10)
{
tmp = y % 10;
for(i = 0; i < 8; i++)
if(buf[i] == tmp && buf[i] != -1)
{
buf[i] = -1;
break;
}
}
}
int main(void)
{
int8_t buf[8];
int y = 21 ,z = 60, n = 1260;
*((uint64_t*) buf) = NEG;
ITOC(buf, n);
ncmp(buf, y);
ncmp(buf, z);
if( *((uint64_t*) buf) == NEG )
printf("%d = %d * %d\n", n, y, z);
return 0;
}
我不理解这一部分:
if( *((uint64_t*) buf) == NEG )
如果变量具有以下值:
y = 21 z = 60 n = 1260
条件为真,但如果这些值包含:
y = 18 z = 81 n = 1458
在这种情况下,第一个位置 buf 为-1,如果 if 仅将第一个位置与 NEG 进行比较,则也应为true。
有人可以解释会发生什么吗?
答案 0 :(得分:5)
我不知道你在哪里找到这段代码,但它肯定不会做你认为的那样。
你认为它做的是检查某种乘法。可能是因为它打印了&#34; n = y * z&#34;在末尾。但实际上它需要n
的数字,并删除y
和z
的数字。如果删除了所有数字,则会打印该消息。例如:
1111 = 11 * 11 true
1234 = 12 * 34 true
1500 = 10 * 50 true
1500 = 30 * 50 false
1458 = 18 * 81 false
1458 = 14 * 58 true
1458 = 45 * 18 true
答案 1 :(得分:1)
在代码的顶部,您可以看到
#define NEG ~0x0LL
因此NEG
是0x0LL
的逐位反转,代表(long long)0。因此,NEG
是一个很长的长度,所有位都设置为1。
了解您的问题:
首先,修复未定义的行为,分配您的buf
(您需要stdlib.h
)
int8_t * buf;
buf = malloc(sizeof(* buf) * 8);
然后使用表达式buf
将调试器附加到(uint64_t *)buf
,并将其视图属性作为uint8的向量(或调试器中的等效项)附加。通过这种方式,您实际上可以看到您的变量已完成的操作以及为什么它在这些特定值上失败。
需要注意的一点是:设置buf[i]
相当于由于数据类型而将相应位设置为0xff
。
您的代码根本不会执行思考它所做的事情。
答案 2 :(得分:0)
如上所述Nit,您将NEG定义为64位设置为1。 然后你做了什么:
*((uint64_t*) buf) = NEG
所以你将64位设置为buf指向的64位数据中的一个。
然后,当你进行检查时:
if( *((uint64_t*) buf) == NEG )
将buf指向的64位与设置为1的64位进行比较。
你似乎想要做的只是比较8位:
if( *((uint8_t*) buf) == (uint8_t)NEG )
我只是回应:
, if the if only compares the first position
因为if比较了铸造所要求的64位数据:)