2

I want to copy an unsigned long integer to char buffer byte by byte. If I use the line under comment, it is not copied to buffer.

    char buf[128];
    //unsigned long int_val = 268435456;
    unsigned long int_val = 293456376;

    cout << "Value of int_val: " << int_val << endl;

    memset(buf, 0, sizeof(buf));

    memcpy(buf, &int_val, sizeof(long));
    cout << "Value after unsigned long int copy - buf: " << buf << endl;

    const int len = strlen(buf);
    cout << "buf" << endl << "====" << endl;
    for (int i = 0; i < len; i++)
    {
        printf("%3d (0x%02X)\n", buf[i], buf[i]);
    }

Following is the output of two runs with each value:

Value of int_val: 268435456
Value after unsigned long int copy - buf:
buf
===

Value of int_val: 293456376
Value after unsigned long int copy - buf: ��}
buf
===
 -8 (0xFFFFFFF8)
-55 (0xFFFFFFC9)
125 (0x7D)
 17 (0x11)
  • 9
    A buffer full of random bytes is not a string, you cannot use `strlen` on it and you cannot print it. Also, it is best to avoid mixing stdio and iostreams, even if only for the reasons of aesthetics. – n. m. could be an AI Oct 26 '20 at 10:24
  • 2
    You treat `buf` like a null-terminates byte string in multiple places, but it isn't that. – Some programmer dude Oct 26 '20 at 10:24
  • 1
    What output do you expect instead? Do you realise what printing a `char` pointer does? – underscore_d Oct 26 '20 at 10:24
  • 2
    Does this answer your question? [strlen() gives wrong size cause of null bytes in array](https://stackoverflow.com/questions/11827531/strlen-gives-wrong-size-cause-of-null-bytes-in-array) or [printing a char pointer … what happens?](https://stackoverflow.com/questions/27626795/printing-a-char-pointer-what-happens) or etc. – underscore_d Oct 26 '20 at 10:25
  • 4
    You forgot to mention in your question what exactly it is you find weird. What did you expect the result to be? – Nikos C. Oct 26 '20 at 10:30
  • It is not about strlen or printing a meaningful value. In one case memcpy can copy the bytes to buffer, but in other case it cannot. Please focus on that. I also tried null terminating the char buffer, it is not a solution. The problem is why the copy operation does not work in one case. – Coşkun Deniz Oct 26 '20 at 10:33
  • 1
    Just adding a `NUL` cannot fix this, because what if the component bytes of the original integer already happen to contain a byte that is all `0` bits? Then the `strlen()` will conclude there are fewer bytes than you want. Why try to use `strlen()` at all; why not just print the `sizeof(unsigned long)` bytes, since it's always going to be that? What you are doing does not make sense, so that needs resolved before we can be sure there is an actual question. – underscore_d Oct 26 '20 at 10:35
  • Printing the buffer is pointless since it'll most likely contain character sequences that can't be displayed properly. To just examine the buffer, you could do [like this](https://godbolt.org/z/WGoqY7) instead. – Ted Lyngmo Oct 26 '20 at 10:49

2 Answers2

5

it is not copied to buffer.

Yes it is.

cout << ... << buf << endl;
const int len = strlen(buf);

It is unclear why you didn't expect the output that you see. 0 is the value of the null terminator character. If the lowest memory order byte of the integer is 0, then the buffer contains the null terminated string that represents the empty string. In such case, the output that you see is to be expected. On little endian systems (and also on big endian systems where long is wider than 4 bytes) that happens to be the case for 268435456 which is 0x10'00'00'00 in hexadecimal.

Just because the bytes that you copied represent the empty string, doesn't mean that the bytes weren't copied.

eerorika
  • 232,697
  • 12
  • 197
  • 326
4

In hexadecimal, 268435456 is 1000000016. Your C++ stores the bytes of an unsigned long in memory with the low-value byte earlier in memory, so this is stored in memory as bytes with values 0016, 0016, 0016, 1016.

memcpy correctly copies these bytes into buf.

Then, when strlen(buf) examines buf, it finds a null byte (0016) first. This indicates the character string in buf has zero length, as the terminating character appears immediately at the beginning. So strlen(buf) returns zero.

Since this return value is assigned to len, the loop for (int i = 0; i < len; i++) performs zero iterations.

Similarly, in cout << "Value after unsigned long int copy - buf: " << buf << endl;, buf contains a string of zero length, so no characters are printed for it.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312