Comparing results after integer promotion

0

Following situation:

I have macros for storing the complement of a variable together with its original value within a structure. With another macro I want to check if the original value is equal to the complement of the stored complement value. But strangely I do not get the results I may expect. Simplifying the operation, this results in following situation:

#include <stdbool.h>
#include <stdint.h>
#define CHECKVAR(var__, compl__) ((var__^compl__)==-1);

int main()
{
uint8_t var;
uint8_t complementvar;

var=3;
complementvar=~var;

bool checkOK=CHECKVAR(var,complementvar); /*-> I expect that all bits are set and hereby it is equal to "-1", but instead i get "false" */

return 0;
}

My expectation would be (e.g. on a 32bit system :

  1. after the complement operation complementvar has the value 0xfffffffc (after integer promotion caused by the ~ operator to int and assigning the lvalue to complementvar by implicitly casting it down to uint8).
  2. now to the checking macro: the bitwise operation leads to an integer promotion on both sides?:
    • 2a). var: 0000 0000 0000 0000 0000 0000 0000 0011; complementvar: 1111 1111 1111 1111 1111 1111 1111 1100
    • 2b)\ now XOR-ing both var and complementvar shoudl result in 1111 1111 1111 1111 1111 1111 1111 1111
  3. checking the results of the XOR-operation together with -1 (represented as an integer) 1111 1111 1111 1111 1111 1111 1111 1111==1111 1111 1111 1111 1111 1111 1111 1111 shall result in true, but instead i always receive false, because the result of XOR-operation (strangely for me) is 0x000000ff?

What compiler am I using? It's the MSVC++11, but actually the solution should be as compiler independent as possible. As I have to be portable too, would the results be different with a C compiler?

c++
c
integer
bit-manipulation
integer-promotion
asked on Stack Overflow Jul 30, 2018 by mbed_dev

1 Answer

3

after the complement operation complementvar has the value 0xfffffffc

No. Look at that code:

uint8_t complementvar;
complementvar=~var;

~var will evaluate to the value you expect, but complementvar has type uint8_t, so the conversion leads to just 0xfc.

In your checking step, this is promoted again to int, but as uint8_t is an unsigned type, no sign extension happens here, you just get 0 bits added. This explains the result you get from xoring (^).

answered on Stack Overflow Jul 30, 2018 by (unknown user) • edited Jul 30, 2018 by (unknown user)

User contributions licensed under CC BY-SA 3.0