1

I write method to bit shift by one in array and save to second array. Let me explain on below example:

 unsigned int firstNumber[2]  = { 0x00000001, 0x8FFFFFFF };
 unsigned int resultNumber[2];

And result should be:

unsigned int resultNumber[2] = { 0x00000000, 0xC7FFFFFF };

Below this is my function:

void bitShiftByOneInRight_1(unsigned int firstNumber[2], unsigned int resultNumber[2]) 
{
    unsigned int lastBitEnabled = 0;
    unsigned int mask = 1;

    for (unsigned int i = 0; i < 2; i++) {
        resultNumber[i] = 0;
        //  example        11001101 & 00000001 for uint8_t
        unsigned int lastBit = (firstNumber[i] & mask) << (sizeof(unsigned int)*8 - 1);

        resultNumber[i] = firstNumber[i] >> 1;
        resultNumber[i] = firstNumber[i] | lastBitEnabled;
        lastBitEnabled  = lastBit;
    }
}

I get answer as the same array firstNumber[2]:

unsigned int resultNumber[2] = { 0x00000001, 0x8FFFFFFF };

Simple example, we have array: [0b00000001, 0b01111111] then answer should be [0b00000000, 0b10111111]

Furthermore when function is this form, which mean use one argument as input and output method, work correctly:

void bitShiftByOneInRight(unsigned int firstNumber[2]) {
    unsigned int lastBitEnabled = 0;
    unsigned int mask = 1;

    for (unsigned int i = 0; i < 2; i++) {

        //  example         11001101 & 00000001 for uint8_t
        unsigned int lastBit = (firstNumber[i] & mask) << (sizeof(unsigned int)*8 - 1);

        firstNumber[i] = firstNumber[i] >> 1;
        firstNumber[i] = firstNumber[i] | lastBitEnabled;
        lastBitEnabled = lastBit;
    }

}

Anyone know what I make wrong? Each answer is welcome for me! Thanks

xLukasbx
  • 35
  • 4
  • 8
    C++ clan is at war with the C clan. Choose your side please. –  Jun 03 '17 at 17:29
  • 1
    @RawN Kind of a strange way to put it, but yes. C and C++ are very different languages and you should usually choose only one when tagging your questions. In this case, all the code is valid C. – Justin Jun 03 '17 at 17:29
  • 2
    Please read about [how to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Some programmer dude Jun 03 '17 at 17:32
  • 1
    @Stargateur A good reason to close for lack of [MCVE]. – EOF Jun 03 '17 at 17:33
  • What is the idea of this "program"? Shift right with carry to another array element (so in the fact 2x wide word than unsigned)? – 0___________ Jun 03 '17 at 17:41
  • Yes, example [0000001, 01111111] then answer is [00000000, 11111111] – xLukasbx Jun 03 '17 at 17:46
  • @Stargateur Yes LENGTH is as 2. My mistake – xLukasbx Jun 03 '17 at 17:46
  • 1
    More confused than ever, why isn't your commented result `[00000000, 10111111]`? – Weather Vane Jun 03 '17 at 17:53
  • @EOF Is lack of mcve actually a sufficient reason to close by StackOverflow rules? I agree that most answerable questions have a mcve and totally am a fan. But there is for example no available flag "lack of MCVE". I agree, a question should either have one or explain why not; but closing with this single reason seems harsh. – Yunnosch Jun 03 '17 at 17:58
  • @Weather Vane exactly, you are right! I am to hurry in write comment. – xLukasbx Jun 03 '17 at 17:58
  • I recommend making a [mcve]. *(Note the difference that I do not vote for closing for the lack of it.)* – Yunnosch Jun 03 '17 at 18:01
  • @tambre "Tag as C++, as the code has initialization lists, which aren't available in C." ??? Where did you see an initialization lists in the OP code ? – Stargateur Jun 03 '17 at 19:27

3 Answers3

1

Something like:

#include <stdio.h>

void shift_right(unsigned *dst, unsigned *src, size_t len) {
  if (len == 0) return;
  for (size_t i = len - 1; i > 0; i--) 
    dst[i] = (src[i] >> 1) + (src[i - 1] & 1u) * ~(~0u >> 1);
  dst[0] = src[0] >> 1;
}

int main(void) {
  unsigned int firstNumber[]  = { 0x00000001u, 0x8FFFFFFFu }, secondNumber[2];
  shift_right(secondNumber, firstNumber, 2);
  printf("%08x, %08x", secondNumber[0], secondNumber[1]);
}

This can be called with source and destination as the same array.

It works for all widths of unsigned.

Although some will question using multiplication, it turns out gcc does a great job of optimizing this to a shift and add that are essentially the same as vicatcu@'s, but auto-adjusted for width.

Gene
  • 46,253
  • 4
  • 58
  • 96
0
#include <stdio.h>
#include <stdint.h>

void shift_right(uint32_t *dst, uint32_t *src, size_t len) {
  if (len == 0) return;
  for (size_t i = len - 1; i > 0; i--){
    dst[i] = (src[i] >> 1) | (src[i-1] << 31);
  }  
  dst[0] = src[0] >> 1;
}
vicatcu
  • 5,407
  • 7
  • 41
  • 65
0

Did you take the one argument form and tweak it so it has separate input and output arguments? Look more closely at these two lines, they aren't doing what you think at first glance.

    resultNumber[i] = firstNumber[i] >> 1;
    resultNumber[i] = firstNumber[i] | lastBitEnabled;
Mic
  • 331
  • 1
  • 4