-1

I'm trying to bit shift char values into an unsigned long long (or an uint64_t, or an __int64), and whenever I try to bit shift by values greater than 32, it appears to subtract 32 from the size of the bit shift.

Other questions listed here a duplicates don't immediately state that a char will be upgraded to only an int instead of an unsigned long long. Because this was not apparent to me, I didn't know that the rule of not shifting a bit-shifting a value by longer that its size was relevant.

The comments pointed out that the char only becomes an int and therefore can't isn't upgraded to a 64-bit int before assignment.

Code


#include <stdint.h>
#include <iostream>
#include <string>
#include <algorithm>


int main(...)
{

    std::string text = "Saturday 2019-08 August-31__08:46:32.38948-pm Pacific Daylight time-phoneid:xxxxxxxxxxx-xxxxxxxx";
    //unsigned int val1, val2, val3;
    //val1 = val2 = val3 = 0;

    //val1 = 't';
    //val1 = val1 << 24;
    //std::cout << val1 << std::endl;


    //unsigned long long hash[12];

    //uint8_t hash_count = 0;
    //uint8_t shift_offset = 7;
    //uint8_t hash_iter = 0;
    for (unsigned int ii = 0; ii < text.size(); ii+=8)
    {
        unsigned long long test_01 = text[ii] << 56   ;
        unsigned long long test_02 = text[ii+1] << 48 ;
        unsigned long long test_03 = text[ii+2] << 40 ;
        unsigned long long test_04 = text[ii+3] << 32 ;
        unsigned long long test_05 = text[ii+4] << 24 ;
        unsigned long long test_06 = text[ii+5] << 16 ;
        unsigned long long test_07 = text[ii+6] << 8  ;
        unsigned long long test_08 = text[ii+7] << 0;


        //hash_iter++;
    }


    return 0;
}

How do I know it's not working?

I'm looking at the values inside the memory window in Visual Studio

System

Windows 10 Visual Studio 2015 Compile Configuration: Debug, x64

Andrew
  • 1,423
  • 1
  • 17
  • 26
  • E.g. `text[ii]` is a single `char`, which might or might not be signed. If you want to shift it more than 7 bits you need to convert it to a 64-bit type first like `static_cast(text[ii])`. And remember, the assignment to the variable `test_01` is done *after* the 8-bit integers are shifted lots of bits. – Some programmer dude Aug 09 '19 at 04:45
  • `char` will be promoted to int, and since `int` is a 32-bit type in this case, shifting it more than 31 invokes undefined behavior. [C left shift on 64 bits fail](https://stackoverflow.com/q/10048047/995714), [how to use uint64_t in C](https://stackoverflow.com/q/43060408/995714), [What does the C standard say about bitshifting more bits than the width of type?](https://stackoverflow.com/q/11270492/995714) – phuclv Aug 09 '19 at 04:53
  • 1
    Whatever is at the left side of the `=` does not influence what happens at the right side. There is no `unsigned long long` at the right side. – n. m. could be an AI Aug 09 '19 at 04:55
  • @Someprogrammerdude... I am able to shift the `char` up to 24 bits. – Andrew Aug 09 '19 at 05:02
  • @phuclv... please see that I'm dealing with `unsigned long long` – Andrew Aug 09 '19 at 05:02
  • 1
    @Andrew please read the links I commented. `text[ii]` is a char and not long long. Clearly shifting it left 24 bit works because char here contains only 8 bits – phuclv Aug 09 '19 at 05:05
  • @phuclv... Roger that... I see them now. Thank you – Andrew Aug 09 '19 at 05:06

1 Answers1

2

text[ii] is a single char which will be promoted to int to perform binary operation. It is not possible to shift a bit more then the width.

You can easily detect it with compiler warning: Live

To solve the problem you can simply cast the type:

char a='a';
uint64_t x = (uint64_t)a<<45;
Oblivion
  • 7,176
  • 2
  • 14
  • 33
  • your edit with example code made this a relevant answer and is now accepted. Thank you – Andrew Aug 09 '19 at 05:14
  • @Andrew I shared a wrong link in my previous edit. I was checking if he compiler distinguishes the type of a temporary literal correctly and forget to edit the type :) – Oblivion Aug 09 '19 at 05:18