2

I got an array of char with 8 positions(char data[8];), this array has an unsigned long long int value on it (8 bytes of size)... data[0] has the first byte of the long long int, data[1] has the second and so on. My question is how to put that value again on an unsigned long long variable?

I've tried shifts but the value wasn't equal de original value, how can i do this without changing the original array...

The order of the bytes is little endian the normal order of variables (from Hight bit to low bit)

Here is a code that prints a different value than expected.

char vec[8]={0,0,0,0,0,0,0,1};

unsigned long long value = *((unsigned long long*) vec);

std::cout<<value;

return 0;

The result should be one but instead is 72057594037927936. Thank you for your patience.

user1553386
  • 143
  • 1
  • 1
  • 8
  • The "first" byte of an `unsigned long long` value, can be either the most significant or the least significant. And you say you've "tried shifts"; please show us your actual code and some sample inputs and outputs. – Keith Thompson Jul 26 '12 at 04:28
  • @user1553386: "Little-endian" means that the least-significant byte is located in memory *first*, which means that in your array the least-significant byte must go first. In memory of little-endian platform value `1` is represented by byte array `{ 1,0,0,0,0,0,0,0,0 }`. The array in your example indeed represents `72057594037927936`, as it should. The code works as it should work. You either misunderstand what little-endian is or you actualy need big-endian. – AnT stands with Russia Jul 26 '12 at 14:39

4 Answers4

4

Assuming the byte order of your data array is the same as the resultant long long value

unsigned long long ll;
assert(sizeof ll == sizeof data);
memcpy(&ll, data, sizeof ll);

Avoid cast-based solutions. They violate strict-aliasing semantics and, for that reason, not guaranteed to work.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Strict-aliasing is explain here, just in case: http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule – nhahtdh Jul 26 '12 at 04:02
  • that doesnt work too, the output of this code is 72057594037927936 on char data[8]={0,0,0,0,0,0,0,1} – user1553386 Jul 26 '12 at 14:29
  • 1
    @user1553386: As I said, this code will only work if the *byte orders are the same*. Your array of bytes `data` represents value `72057594037927936` on little-endian platform and `1` on big-endian platform. You need to decide which platform you are using and act accordingly. – AnT stands with Russia Jul 26 '12 at 14:42
1

You can do:

unsigned long long value = *((unsigned long long*) data);

But this assumes that:

  1. data is properly aligned to be accessed as a long long. For example, if long long requires 8-byte alignment but data is only 4-byte aligned, it can Do Bad Things.
  2. The bytes of data are stored in the same order as the current machine's byte order for long long. See Endianness.
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
  • 1
    @LuchianGrigore: How would you make it less verbose? (But it's still subject to both alignment and endianness problems.) – Keith Thompson Jul 26 '12 at 04:27
  • @LuchianGrigore: The tag you were looking for is -- but it doesn't work in comments anyway. – Keith Thompson Jul 26 '12 at 05:35
  • I really want to know about (all) the flaws of this method. I'd appreciate if anyone would edit my post, or write an answer that include references to potential problems. I heard of alignment in a struct, but I don't know how it can be applied here. And AndreyT mentioned about aliasing problem, but from a white paper linked by an SO answer doesn't seem to related to this. – nhahtdh Jul 26 '12 at 05:43
1

Direct cast may not work depending on the hardware representation, this should work in most cases:

long long to_llong(unsigned char *data) {
    long long v = 0;
    for (int i = 0; i < 8; i++) {
      v = (v << 8) | data[i];
    }
    return v;
}
perreal
  • 94,503
  • 21
  • 155
  • 181
0

What do you mean by saying the first byte? It's the least significant byte or the most significant byte?

The answer to that question decides whether the number value is little-endian or big-endian. wikipedia link

If the value's endian style is the same with your system, you can just directly cast the address of the first byte to "unsigned long long *", while you will have to convert its endian style if it's no the same.

Gang YIN
  • 2,509
  • 2
  • 21
  • 25