Complement operator turning uint8_t to signed number

Hi I am Siddhesh and I am an intermediate level arduino user,
I am trying to read PORT C and check for different combinations at port C from the eight relay

My doubt is

when I use complement(~ operator) after left shifting(<< operator) a uint8_t number is just gives me answer in 16 bit form

My Code:-

enum relay_pins {START, UP, DOWN, LEFT, RIGHT, FWD, REV, ALARM};
int port_c=254;
uint8_t spam=1;

void setup()
{ Serial.begin(115200);
   

Serial.println(sizeof(spam));
Serial.println(sizeof(~(spam)));
Serial.println(sizeof(spam<<LEFT));

}

void loop()
{
  
}
  

Output:-
1
2
2

for my doubt, sorry if this is a silly question but just started to learn in deep of bit manipulation

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use [color = red]code tags[/color] (the </> icon above the compose window) to make it easier to read and copy for examination

What is the question?

Why a shift or complement operator converting a unsigned 8 bit integer to signed integer of 16 bits

My Code:-

enum relay_pins {START, UP, DOWN, LEFT, RIGHT, FWD, REV, ALARM};
int port_c=254;
uint8_t spam=1;

void setup()
{ Serial.begin(115200);
   

Serial.println(sizeof(spam));
Serial.println(sizeof(~(spam)));
Serial.println(sizeof(spam<<LEFT));

}

void loop()
{
  
}
  

Output:-
1
2
2

Do not post images of code or Serial monitor output. Follow the advice in the link I posted

Done sir, can you please guide me on the issue?

This is because of numeric promotion. Bitwise operators work on integers, when smaller types are used they are automatically promoted.

https://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions

[edit]

By the way, here is a trick that may help when you want to know the type of a value.

template <class T> void show(T) {
  Serial.println(__PRETTY_FUNCTION__);
}

void setup() {
  // ...
  show('a');
  show('a' << 1);
}

This results in:

void show(T) [with T = char]
void show(T) [with T = int]
1 Like

Thanks, it really helped me understand, I worked around it by just converting it again into a uint8_t after doing my << and ~ operations.
Is there any more effecient way?

My workaround:-

uint8_t spam=1;

Serial.println(sizeof(spam));  // 8bit unsigned

Serial.println(sizeof(~(spam)));  // 16 bit signed

Serial.println(sizeof(spam<<LEFT));  // 16 bit signed

Serial.println (uint8_t(~(spam<<START))) ; // 8 bit unsigned

not too sure what you're are trying to achieve, but simply writing this as code ensures that 'spam' is always an 8bit unsigned value...

enum relay_pins {START, UP, DOWN, LEFT, RIGHT, FWD, REV, ALARM};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

uint8_t spam=1;

Serial.println(sizeof(spam));  // 8bit unsigned

spam = ~spam;

Serial.println(sizeof(spam)); //8 bit unsigned

spam<<=LEFT;

Serial.println(sizeof(spam));  //8 bit unsigned

spam = ~(spam<<START);

Serial.println (sizeof(spam)); //8 bit unsigned
}

void loop() {
  // put your main code here, to run repeatedly:

}

hope that helps....

1 Like

Not that I know of. It will be converted back to an uint8_t as soon as you assign it to a variable of that type.

If it really bothers you, perhaps you can use a function, e.g.,

uint8_t shl(uint8_t const v, size_t const n) {
  return v << n;
}
1 Like

Works great!!

Thanks for the help got it :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.