2

I am working wiht pic32mx controller and using the C32 toolsuite v2.02 compiler amd MPLAB-X IDE v 3.05. I am using the bit wise operation with the long long variable but getting erroneous result.

int main()

{

    long long data0, data1=0;

    data0 = 489631651402;
    data1 = data0 & 0x0FFFFFFFFFF;

    printf("%llu\n%llu\n", data0, data1 );

    return 0;
}

OUTPUT:

    489631651402

    492260348528

According to calculation this result is erroneous. data0 and data1 must be equal.

Please suggest me any better way for this operation. if there's any error in above procedure please suggest the right path.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Did you have a look at the generated assembly code ? – Jabberwocky Apr 08 '16 at 10:10
  • 3
    So the number becomes *larger* when you bitwise-and it with a constant? Hm ... That's normally not very possible. I suggest you double-check this, and also why not print the numbers in hex, to make them slightly more understandable? Plus what Joachim said in his deleted answer, not sure why that's gone. – unwind Apr 08 '16 at 10:19
  • The only problem i see with this code is using the `%llu` specifier with signed values. I doubt that would cause this error though. – interjay Apr 08 '16 at 10:27
  • 1
    Please check this http://www.microchip.com/forums/m488183.aspx, I am not sure if this issue is related (you never know with C32) but it is worth of trying... – Darko Djuric Apr 08 '16 at 10:34
  • It seems that the C32 compiler support for 64-bit types is flaky at best. First of all it seems to be an extension bolted onto a compiler basically supporting only C90 (as told in the forum thread linked to by @DarkoDjuric); Secondly the compiler have to generate all code to handle 64-bit types and 64-bit arithmetic since the CPU doesn't support it natively, so it is possible that you found a bug in their compiler for handling 64-bit integer types. – Some programmer dude Apr 08 '16 at 10:43
  • 1
    I'm with you on that - maybe it would be worth trying to designate the constant with `LL` in order to help the compiler see it is a `long long` constant? – tofro Apr 08 '16 at 10:47
  • Smells like a compiler bug where the compiler picks the wrong type for literals. MPLAB has a very poor reputation in general. – Lundin Apr 08 '16 at 10:51
  • It might also be useful to print out the value of the constant - both directly and after assigning just the constant to a `long long` variable. – Andrew Henle Apr 08 '16 at 10:56
  • Totally unrelated to the problem and won't help: I find it good practice to fill hex constants used as masks with leading zeroes to their maximum extent - Makes it easier to see what is actually happening and avoids confusion like in one of the (wrong) answers below. Humans can (at best) realize ~6 'F's in a row – tofro Apr 08 '16 at 11:04
  • I would highly recommend migration to XC32 (new version of Microchip compiler) since C32 is not supported for at least two years... also there is MplabX v3.26 – Darko Djuric Apr 08 '16 at 11:20

1 Answers1

-1

Use ULLONG_MAX as the constant if you need a mask for all of the bits. Use 0x0FFFFFFFFFFLL if you need to mask only those 48 bits

GMichael
  • 2,726
  • 1
  • 20
  • 30
  • `ULLONG_MAX` is always more than `0x0FFFFFFFFFF`. And its value is not guaranteed to be equal to anything (there's only a lower bound), so it wouldn't be a good idea to use it anyway. – interjay Apr 08 '16 at 10:15
  • The object that was undergoing bitwise AND is of the long long type. – GMichael Apr 08 '16 at 10:19
  • I know it is, but that doesn't explain why you think `ULLONG_MAX` is a good replacement for `0x0FFFFFFFFFF`. – interjay Apr 08 '16 at 10:25
  • @interjay Are you sure? The text uses the word magnitude: *Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.* Doesn't that indicate power of 2 -1 ? – 2501 Apr 08 '16 at 10:25
  • Since we do not know the purpose of that bitwise AND, both you and I can be correct. I'll edit the answer – GMichael Apr 08 '16 at 10:29
  • @2501 I didn't say anything about powers of 2, so I don't know what you are referring to. This answer is wrong because the original code used `0x0FFFFFFFFFF`, while `ULLONG_MAX` is at least `0xFFFFFFFFFFFFFFFF`. Additionally, it doesn't make any sense to AND with `ULLONG_MAX` because it will never change the number. – interjay Apr 08 '16 at 10:34
  • @interjay I was referring to this: *And its value is not guaranteed to be equal to anything (there's only a lower bound),* – 2501 Apr 08 '16 at 10:35
  • @2501 By that, I only meant that you shouldn't use `ULLONG_MAX` if what you actually need is a specific value, because its value can be different on various implementations. – interjay Apr 08 '16 at 10:36
  • @interjay Yes I know what you mean by that. I asked a question. Let me repeat it: doesn't the C Standard guarantee that a max value is in the form: `2^n-1`, and not some arbitrary value? – 2501 Apr 08 '16 at 10:37
  • @interjay Ah I found it: *6.2.6.2, p 1:*. The max value must be in the form 2^n-1. – 2501 Apr 08 '16 at 10:42
  • @2501 Yes, that's probably true (at least for unsigned values). But not really relevant to what I said above. – interjay Apr 08 '16 at 10:46