不寻常的条件(*((uint64_t *)buf)== NEG)

时间:2014-12-17 01:07:07

标签: c

案例是我正在研究我在互联网上发现的引起我注意的代码,是这样的:

#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。

有人可以解释会发生什么吗?

3 个答案:

答案 0 :(得分:5)

我不知道你在哪里找到这段代码,但它肯定不会做你认为的那样。

你认为它做的是检查某种乘法。可能是因为它打印了&#34; n = y * z&#34;在末尾。但实际上它需要n的数字,并删除yz的数字。如果删除了所有数字,则会打印该消息。例如:

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

因此NEG0x0LL的逐位反转,代表(long long)0。因此,NEG是一个很长的长度,所有位都设置为1。

了解您的问题:

首先,修复未定义的行为,分配您的buf(您需要stdlib.h

int8_t * buf;
buf = malloc(sizeof(* buf) * 8);

然后使用表达式buf将调试器附加到(uint64_t *)buf,并将其视图属性作为uint8的向量(或调试器中的等效项)附加。通过这种方式,您实际上可以看到您的变量已完成的操作以及为什么它在这些特定值上失败。

Sample debugger image

需要注意的一点是:设置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位数据:)