Problems with bitshifting function

Hello Arduino community:

I am trying to make a function that can take an 8 bit binary number and shift it however many places I want to the left. I am creating a function because the bitshift operator (<<) takes away any zeros that may be on the left, so for example if i shifted 11001100 2 times to the left I would receive 1100 in return but i need those leftmost zeros to stay. The code for the function alone is shown below. In the specific case of what i have running in my void loop I’m getting 1001 one printed in the serial bar but i don’t understand why. If anyone could help me find a way to just simply shift an 8 bit binary number to the left without it disregarding the leftmost zeros or help me fix my code so that it does it for me I’d be very appreciative.

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

}

void loop() {

  byte x = 00110011;
  shiftleft(x, 1);
  Serial.println(x, BIN);
}

void shiftleft(int tbs, int shiftamount){  //tbs = to be shifted
  byte newbyte;
  for(int x=0; x<(8-shiftamount); x++)              
  {
    byte newFirstBit = (bitRead(tbs, (7 - shiftamount - x)));  
    bitWrite(tbs, x, newFirstBit); 
  }
  
  for(int y=0; y<shiftamount; y++)
  {
    bitWrite(newbyte, y, 0);
  }
  tbs = newbyte;      
}

I don't know what your program does, but if you shift a byte 2 bits left, two zeros are inserted on the two low order bits. So, your example would result in: 00110000, not 00001100. If you then shifted this right two bits, you would get: 00001100, which I think is the result you wanted.

Paul

I shifted 11001100 2 times to the left I would receive 1100 in return but i need those leftmost zeros to stay]

Why can you not use a unsigned long?

Just because Serial.print doesn’t print the zeros doesn’t mean they aren’t there. It just drops leading zeros because they aren’t significant.
You have several problems with your code. One is that you aren’t testing what you think you are.

byte x = 00110011;

does not set x to the bit pattern 00110011. It sets it to the OCTAL number 00110011 which is the bit pattern 001001000000001001. In C/C++, a leading zero on a number indicates an octal number.
You’d be a lot better off just using the left shift operator <<

Pete

so @ el_supremo if i was shifting data out to 8 bit shift registers and used the << operator it wouldn’t get rid of the leading zeros?

This code doesn’t do what you think it does. Here are some of the issues:

The first is noted above by el supremo, so I won’t belabor it.

The function definitionvoid shiftleft(int tbs, int shiftamount){shows that the input value tbs is passed by value. That means that the final value of tbs will be discarded when the function exits. When you send x to shiftleft(), x doesn’t change. There are a few ways to fix it:

One: Change the function definition to return a byte, add a line to the function to return the final value of tbs, and assign the return value of the function to x in loop().

Two: Using C conventions, change the function definition and the call to pass tbs / x by reference, like this:void shiftleft(int* tbs, int shiftamount){and change the references to tbs to *tbs. That passes the address of tbs to the function, and the function then operates on the value that the address points to, and stores the results when it terminates.

Three: Using C++ conventions, change the function definition to pass tbs by reference, and, except as noted below, leave the rest of the code alone, like this:void shiftleft(int &tbs, int shiftamount){That tells the compiler that tbs will be an address rather than a value, and C++ will treat is that way throughout the function.

I like the C conventions better, because it’s always clear to me what kind of objects the function arguments really are. The C++ convention seems to obfuscate that information, in my view. But, I learned C first, so that may just reflect my bias.

You’ll need to make sure that x and tbs are the same type to pass by reference. The compiler treats various kinds of integer data as compatible when they’re passed by value, but seems to insist on a strict match when they’re passed as pointers.

The variable newbyte isn’t initialized in the function. Because it’s a local automatic variable, it won’t be initialized to zero, and it will have whatever value was lying around in memory when the function executes. That will garble the final value. I think that you want to set the value of newbyte to zero when you declare it, but I’m not sure.

The function reads bits from tbs, and it writes bits to tbs. The only things it writes to newbyte are zeros, so, if you initialize newbyte to zero, it will always be zero. I think that you intended to read from tbs, and write to newbyte. But, I’m not sure.

When I make all those corrections, the code seems to work.

I think that you’re laboring under the misconception that leading zeros somehow disappear when they’re shifted. It may be that all you need is a routine to print a number in binary that shows leading zeros. Serial.print() doesn’t show them. I think that you could write a routine that prints bitRead() of the leftmost bit, and works its way down to the least significant bit, printing bitRead() of each in turn. I think, but can’t tell for sure, that you’d be satisfied with the results. Then you could just use the operator <<.

cabyambo:
so @ el_supremo if i was shifting data out to 8 bit shift registers and used the << operator it wouldn’t get rid of the leading zeros?

Correct, it will not “get rid of the leading zeros”. If you shift a byte into an 8bit shift register, it will shift the whole byte, which is composed of 8 bits. If the leading bits are zeros, they will still be sent.

The leading 0’s aren’t shown when you print it, because when writing numbers, one does not include leading zeros (consider the case of the number 5 in decimal - we write it “5”, not “005” or “00005” - even though there’s a 0 in the 10’s place and 100’s place etc). This behavior is indeed very annoying when reading binary numbers because you always want the leading zeros shown. (reading 32 bit registers on the STM32 processors printed out like that is reaaal fun. 32 bits, leading zeros chopped off by the formatting… so you have to count up to 32 characters from the right, even if you happen to care only about bit 29 or something),

Let's take the number 1234. How many leading zeros are there? One answer: there are an infinity of them. Another answer: it depends on how many reels your odometer has.

If you don't want to "lose" the left most bits when you shift them, where you you want them put?

Oh, I see: you are attempting to implement a roll function.

How about this?

unsigned int rollLeft(unsigned int x, int n) {
  return (x<<n) | (x>> (16-n));
}