Roughly speaking, you need a method for converting a single value of type long (Signed 64-bit integer according to the specification) into an array of bytes ( unsigned char[] for C ++).

Table for checking control values ​​(i.e., what should be the result):

 // long byte array // ---- ---------- // 0 00-00-00-00-00-00-00-00 // 16777215 FF-FF-FF-00-00-00-00-00 // -16777215 01-00-00-FF-FF-FF-FF-FF // 1000000000 00-CA-9A-3B-00-00-00-00 // -1000000000 00-36-65-C4-FF-FF-FF-FF // 4294967296 00-00-00-00-01-00-00-00 // -4294967296 00-00-00-00-FF-FF-FF-FF // 187649984473770 AA-AA-AA-AA-AA-AA-00-00 // -187649984473770 56-55-55-55-55-55-FF-FF // 1000000000000000000 00-00-64-A7-B3-B6-E0-0D // -1000000000000000000 00-00-9C-58-4C-49-1F-F2 // -9223372036854775808 00-00-00-00-00-00-00-80 // 9223372036854775807 FF-FF-FF-FF-FF-FF-FF-7F 

Problem. With this method of checking negative numbers show an incorrect result !!! :

 long x = -1000000000; // 00-36-65-C4-FF-FF-FF-FF unsigned char *s = (unsigned char *)&x; for (size_t i = 0; i < 8; i++) { printf("%X\r\n", s[i]); } 

Is this a problem with the verification method or the conversion function itself from the answer below?

  • I do not really understand, but what exactly does not suit you? The output corresponds to a table like. - αλεχολυτ 7:01 pm
  • @alexolut, look, the number: -1000000000 should give the result: 00-36-65-C4-FF-FF-FF-FF , but in fact gives the following result: 00-36-65-C4-00-00-00-00 - Alexis 00-36-65-C4-00-00-00-00
  • 00-36-65-C4-FF-FF-FF-FF - αλεχολυτ
  • 2
    Thu. And why did you decide that the size of a long 8 bytes? The loop must be up to sizeof(x) . Anything outside this range is already a trash value. If you want to see FF use long long , but it would be more appropriate to use std::int64_t from <cstdint> . Proof - αλεχολυτ
  • one
    @Alexis See what sizeof(long) equals and be surprised :) - Harry

2 answers 2

Correctly in the idea so:

 long x = -1000000000; // 00-36-65-C4-FF-FF-FF-FF unsigned char *s = (unsigned char *)&x; for (size_t i = 0; i < sizeof(x); i++) // sizeof(x) вместо 8 { printf("%02X\r\n", s[i]); } 

On my VS 2015 gives out (both under target x86, and x64)

 00 36 65 C4 

At the same time, we see that sizeof(long) == 4 under MSVC.


The correct answer was given in the comments before me @alexolut and @Harry.

    Catch

     #include <stdio.h> #include <stdlib.h> #include <stdint.h> void reverse (char *s, int n) { int i = 0; for (--n; i < n; i++, n--) { char t = s[i]; s[i] = s[n]; s[n] = t; } } void print (uint64_t v) { int i = 1; char *litte_endian = (char *)&i, // например, x86 (иначе, м.б. ARM или Sparc) // Про порядок байт в словах можно почитать в https://en.wikipedia.org/wiki/Endianness *t = (char *)&v; if (!*litte_endian) reverse(t, sizeof(v)); for (i = 0; i < sizeof(v); i++) printf("%02x%s", (unsigned char)t[i], i < sizeof(v) - 1 ? "-" : ""); } // 0 00-00-00-00-00-00-00-00 // 16777215 FF-FF-FF-00-00-00-00-00 // -16777215 01-00-00-FF-FF-FF-FF-FF // 1000000000 00-CA-9A-3B-00-00-00-00 // -1000000000 00-36-65-C4-FF-FF-FF-FF // 4294967296 00-00-00-00-01-00-00-00 // -4294967296 00-00-00-00-FF-FF-FF-FF // 187649984473770 AA-AA-AA-AA-AA-AA-00-00 // -187649984473770 56-55-55-55-55-55-FF-FF // 1000000000000000000 00-00-64-A7-B3-B6-E0-0D // -1000000000000000000 00-00-9C-58-4C-49-1F-F2 // -9223372036854775808 00-00-00-00-00-00-00-80 // 9223372036854775807 FF-FF-FF-FF-FF-FF-FF-7F int main (int ac, char *av[]) { int i; int64_t a[] = { 0, 16777215, -16777215, 1000000000, -1000000000, 4294967296, -4294967296, 187649984473770, -187649984473770, 1000000000000000000, -1000000000000000000, -9223372036854775808, 9223372036854775807, }; for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) print(a[i]), puts(""); return puts("End") == EOF; } 

    Since the label is C ++ 11, then we are translating g ++ and running

     avp@avp-ubu1:hashcode$ g++ -O3 -std=c++11 pc && ./a.out pc:61:6: warning: integer constant is so large that it is unsigned -9223372036854775808, ^ 00-00-00-00-00-00-00-00 ff-ff-ff-00-00-00-00-00 01-00-00-ff-ff-ff-ff-ff 00-ca-9a-3b-00-00-00-00 00-36-65-c4-ff-ff-ff-ff 00-00-00-00-01-00-00-00 00-00-00-00-ff-ff-ff-ff aa-aa-aa-aa-aa-aa-00-00 56-55-55-55-55-55-ff-ff 00-00-64-a7-b3-b6-e0-0d 00-00-9c-58-4c-49-1f-f2 00-00-00-00-00-00-00-80 ff-ff-ff-ff-ff-ff-ff-7f End avp@avp-ubu1:hashcode$ uname -a && g++ --version Linux avp-ubu1 4.4.0-34-generic #53-Ubuntu SMP Wed Jul 27 16:06:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux g++.real (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. avp@avp-ubu1:hashcode$ 
    • Hmm, how does it work !*litte_endian ? - VladD
    • @VladD, looks that in the younger (with a smaller address) byte - 0 - big, 1 - little. The TS has an answer for little, so in the big architecture it is necessary to turn the same table to print. - avp
    • Wait, what will be for the value 0xffff00000000ffff or vice versa 0x0000ffffffff0000? - VladD
    • @VladD, the same as with 0000000000000000 or ffffffffffffffffff - reversed into itself. What's so surprising? - avp 8:31 pm
    • OK, then 0xff112233445566ff? I mean, how does the definition of big / little endian work? After all, *little_endian will be 0xff . - VladD 8:32 pm