akahhor
akahhor

Reputation: 139

Bitwise not to how to do without ffffffff

When doing bitwise not, get a lot ffffffff. How to do correctly?

    space := "    "
    str := "12345678999298765432179.170.184.81"

    sp := len(str) % 4
    if sp > 0 {
        str = str + space[0:4-sp]
    }
    fmt.Println(str, len(str))

    hx := hex.EncodeToString([]byte(str))
    ln := len(hx)
    a, _ := strconv.ParseUint(hx[0:8], 16, 0)
    for i := 8; i < ln; i += 8 {
        b, _ := strconv.ParseUint(hx[i:i+8], 16, 0)
        a = a ^ b
    }

    xh := strconv.FormatUint(^a, 16)
    fmt.Println(xh)

output ffffffffc7c7dbcb

I need only c7c7dbcb

Upvotes: 1

Views: 228

Answers (1)

icza
icza

Reputation: 417777

You get a lot of leading ff because your a number in fact is only 32-bit "large" but is used "within" a 64-bit uint64 value. (You're processing numbers with 8 hex digits = 4 bytes data = 32 bit.) It has 4 leading 0 bytes, which when negated will turn into ff. You can verify this with:

fmt.Printf("a %#x\n",a)

Outputs:

a 0x38382434

To get rid of those leading ff, convert the result to uint32:

xh := strconv.FormatUint(uint64(uint32(^a)), 16)
fmt.Println(xh)

(Converting back to uint64 is because strconv.FormatUint() expects / requires uint64.)

This outputs:

c7c7dbcb

Another option is to apply a 0xffffffff bitmask:

xh = strconv.FormatUint(^a&0xffffffff, 16)
fmt.Println(xh)

Also note that you could print it using fmt.Printf() (or fmt.Sprintf() if you need it as a string) where you specify %08x verb which also adds leading zeros should the input has more than 3 leading 0 bits (and thus strconv.FormatUint() would not add leading hex zeros):

fmt.Printf("%08x", uint32(^a))

This outputs the same. Try the examples on the Go Playground.

Upvotes: 5

Related Questions