2 things:
- charcan be signed or unsigned, hence shouldn't be used storing for data types other than characters.
 - In C, C++ and most C-like languages, any types narrower than - intmust be promoted to- intin an expression, and your statement will be treated like this
 -  unsigned long ret = ((int)b[0] << 56) | ((int)b[1] << 48)
                   | ((int)b[2] << 40) | ((int)b[3] << 32)
                   | ((int)b[4] << 24) | ((int)b[5] << 16)
                   | ((int)b[6] <<  8) | ((int)b[7]);
 - If - charis signed, it'll be promoted to- intusing sign extension. As a result the top bits will be filled with 1s if the byte value is negative.
 - In MSVC - charis signed by default. You can use- /Jto make char unsigned, which will solve part of your problem. But then another problem arises:
 
- In Windows - longis a 32-bit type, consequently you can't pack 8 bytes into it. Moreover- intis also 32-bit on most modern systems, and after promoting- b[i]to int shifting more than 31 is undefined behavior which is what your program does.
 
So to fix all the problems portably you need to:
- Cast all b[i]tounsigned charoruint8_t, or masking the high bits by ANDing it with 0xFF like 0605002 suggested. Or simply change the type ofbtounsigned char&*instead ofchar&*
- Change the return type to a type at least 64-bit wide like (unsigned) long long,(u)int64_tor(u)int_least64_t
The result may look like this
uint64_t readAndSkipLong(unsigned char*& b)
{
    return ((uint64_t)b[0] << 56) | ((uint64_t)b[1] << 48)
         | ((uint64_t)b[2] << 40) | ((uint64_t)b[3] << 32)
         | ((uint64_t)b[4] << 24) | ((uint64_t)b[5] << 16)
         | ((uint64_t)b[6] <<  8) | ((uint64_t)b[7]);
}
or
uint64_t readAndSkipLong(char*& b)
{
    return ((uint64_t)(uint8_t)b[0] << 56) | ((uint64_t)(uint8_t)b[1] << 48)
         | ((uint64_t)(uint8_t)b[2] << 40) | ((uint64_t)(uint8_t)b[3] << 32)
         | ((uint64_t)(uint8_t)b[4] << 24) | ((uint64_t)(uint8_t)b[5] << 16)
         | ((uint64_t)(uint8_t)b[6] <<  8) | ((uint64_t)(uint8_t)b[7]);
}
However you don't actually need to write a function to reverse endian. There are already ntohll() and htonll() for that purpose
reversedEndian = ntohll(originalValue);
If the input must be a char array then just copy the value to a uint64_t
memcpy(&originalValue, &b, sizeof originalValue);
reversedEndian = ntohll(originalValue);
You can further reduce the whole thing to reversedEndian = ntohll(*(int64_t*)&b); if strict aliasing is allowed because on x86 unaligned access is generally permitted