1

I'm not sure if this is correct, I have tested it and seems that some bytes are off... Basically, I have the following:

unsigned char szBuffer[1024] = {0};
long long nValue = 1334553536;
memcpy(szBuffer, (char*)&nValue, sizeof(long long));

//

long long nNewValue = reinterpret_cast<long long>(szBuffer);
printf(nNewValue); //prints out a smaller number than previously stated

Would anyone mind pointing out where I went wrong? Thank you.

unwind
  • 391,730
  • 64
  • 469
  • 606
Andy Carter
  • 201
  • 3
  • 12
  • 1
    The first argument to `printf` is a format string; `printf(rNewValue)` probably won't compile. Please post real code. – Keith Thompson Jan 10 '14 at 16:59
  • Originally it was std::cout but then I realized I added the C tag by accident, therefore I changed it to printf() without thinking if it'll compile or not. It's just a minor change. The rest compiles. – Andy Carter Jan 10 '14 at 17:02
  • The C tag is no longer there. Again, please post real code, copy-and-pasted from what you've actually compiled. If you knew what errors in your code are relevant, you wouldn't need to ask the question. http://sscce.org/ – Keith Thompson Jan 10 '14 at 17:04
  • I'm not asking a question based on if it compiles or not. My problem was a logical error at runtime. But I see your point and I'll consider it. The code I have includes parts from other libraries, irrelevant to my actual problem. Therefore I tried to keep it simple. Thanks for the concern. – Andy Carter Jan 10 '14 at 17:08
  • Yes, you should definitely simplify the code and remove dependencies on external libraries if you can, but if you're not asking about a compile-time error, the code you post needs to compile and run. People trying to help you may need to copy-and-paste your code and try it themselves (as I did). Have you read http://sscce.org/? – Keith Thompson Jan 10 '14 at 17:36

3 Answers3

4

You're setting nNewValue to the address of szBuffer, instead of reading data from that address. Use:

long long nNewValue = *reinterpret_cast<long long*>(szBuffer);
Bradley Grainger
  • 27,458
  • 4
  • 91
  • 108
  • Thank you, this seemed to work. Guess I'll have to go over my casting again... – Andy Carter Jan 10 '14 at 16:56
  • Yes, it *seemed* to work. But how do you know that `szBuffer` is correctly aligned to hold a `long long` object? See [my answer](http://stackoverflow.com/a/21050083/827263). – Keith Thompson Jan 10 '14 at 17:02
  • I don't - that's why I'm going to google more about buffer alignment and find out what you mean. Thank you. – Andy Carter Jan 10 '14 at 17:05
1

Change this statement

long long nNewValue = reinterpret_cast<long long>(szBuffer);

to

long long nNewValue = *reinterpret_cast<long long *>(szBuffer);
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Here's a modified version of your program that works on my system (expanded to a complete program):

#include <iostream>
#include <cstring>
int main() {
    unsigned char szBuffer[1024] = {0};
    long long nValue = 1334553536;
    std::memcpy(szBuffer, &nValue, sizeof(long long));
    long long nNewValue = *(reinterpret_cast<long long*>(&szBuffer));
    std::cout << nValue << "\n" << nNewValue << "\n";
}

memcpy's first two parameters are of type void*, so you don't need to cast them; if you do cast them (is that conversion deprecated in C++?), you should cast to void*, not char*.

The assignment to nNewValue converts the address of the buffer to long long*, and then dereferences the converted value.

But this is a bad idea. g++ gives me a warning on the dereference of the converted pointer:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

Furthermore, there is no guarantee that szBuffer, which is an array of unsigned char, is correctly aligned so its first few bytes can safely be treated as a long long object. The x86 or x86_64 system you're most likely using tolerates misaligned memory accesses, but not all systems do so.

Pointer casts are often unsafe unless you know exactly what you're doing.

If you want to reinterpret part of a character array as an object of some other type, you can use a union if you really need to interpret the memory itself as a different type of object, or use memcpy. (Even so, be sure that you really need to do this; it's likely that you don't. Most of the time, if you want to store a long long object, you should just define a long long object.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • If what you're saying is unsafe - then I'll consider doing something else. How about taking the long long's value as an ANSI character, sprintf() then into the buffer, and then atoll() it back to a long long? Would this be better? – Andy Carter Jan 10 '14 at 17:16
  • @AndyCarter: That wouldn't do the same thing. First off, "ANSI character is a misnomer for one of Microsoft's 8-bit character sets such as Windows-1252; even MS doesn't call it that anymore. There is no character with the value 1334553536, so that approach can't work. If your goal is to get `1334553536` as a `long long` value, you've already got it in `nValue`, and there's no need to use the buffer. If your goal is something else, you'll need to tell us just what you're trying to accomplish. (And again, please update your question to show us your actual code.) – Keith Thompson Jan 10 '14 at 17:34
  • You've slightly misunderstood me. Of course there is no character for 1334553536. My idea was to actually put the "string" itself of 1334553536 into the buffer and occupy 10 bytes. But again, I emphasize that there's a lot of code in my project that I'm sure neither you not others have the time to look into it. All I'll say is that I'm implementing an "ping/ms" counter for a network program. You know - get current time (in milliseconds) since 1970, send packet, receive same packet, get current time again and subtract the difference along with any overhead. – Andy Carter Jan 10 '14 at 17:41
  • @AndyCarter: If that's all you'll say, then I can't be of much more help. I don't see how your ping/ms program would require storing large integer values in an array of `unsigned char`. But if you're able to decide how to store the values, you can pick any format you like, including human-readable character sequences. (BTW, 1334553536 is most likely time *in seconds* since 1970, unless it's mid-January of 1970.) – Keith Thompson Jan 10 '14 at 17:51
  • As you said yourself, the code I provided isn't real. 1334553536 is just a value I made up. Since the Epoch (1970) it's more than that (especially in milliseconds), which is why a long long is what I expect to be large enough. By the way - I really appreciate your input and I'm really sorry for being a bother. – Andy Carter Jan 10 '14 at 18:05