1
unsigned long id = 12;
unsigned long age = 14;
unsigned char* pData = new unsigned char[8];
memcpy(pData,&id,4);/* using memcpy to copy */
pData = pData + 4;
memcpy(pData,&age,4);/* using memcpy to copy */
std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;
pData = pData - 4;
std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

Output on linux

14 60129542156

on windows (vc++)

14 12

Anton Savin
  • 40,838
  • 8
  • 54
  • 90
abhi312
  • 364
  • 1
  • 6
  • 25
  • 2
    Looks like a problem with the size of unsigned long in each platform, they might also be 64bit vs. 32bit. Try using sizeof(unsigned long) instead of the literal 4. – bendervader Jun 30 '15 at 06:11
  • 2
    In the Visual Studio compiler `sizeof(long)` is 4 even on 64 bit systems. For GCC on 64 bit systems then `sizeof(long)` is 8. – Some programmer dude Jun 30 '15 at 06:16
  • 1
    you need to use sizeof(unsigned long) – Nick Jun 30 '15 at 06:17
  • check my answer below, do you really need memcpy() ? can't you just use `a[1] = b` or `a = &b` – Nick Jun 30 '15 at 06:32
  • @Nick i saw ur ans. but there u also used memcpy. – abhi312 Jun 30 '15 at 06:40
  • @abhi312: [your last question](http://stackoverflow.com/questions/31129580/store-value-in-pointer-var) got *lots* of answers and comments recommending use of `sizeof` - this one's a bit silly considering.... – Tony Delroy Jun 30 '15 at 06:47
  • 2
    @JoachimPileborg gcc on Windows follows Windows model, so long is 32 bits even on gcc on 64-bit Windows – phuclv Jun 30 '15 at 06:51

5 Answers5

4

You are making the assumption that sizeof(unsigned long) is always 4. This is not true.

Try this:

const size_t NBYTES = sizeof(unsigned long);
unsigned long id = 12;
unsigned long age = 14;
unsigned char* pData = new unsigned char[2 * NBYTES];
memcpy(pData,&id, NBYTES);/* using memcpy to copy */
pData = pData + NBYTES;
memcpy(pData,&age, NBYTES);/* using memcpy to copy */
std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;
pData = pData - NBYTES;
std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

If you want to use explicit data sizes, then use the types defined in <cstdint>. Documentation can be found here.

paddy
  • 60,864
  • 6
  • 61
  • 103
3
memcpy(pData,&id,4);/* using memcpy to copy */
//               ^

You are assuming the sizeof (unsigned long) is 4 which may or may not be true on a system as it is implmentation dependent.

Use the following line for the consistent behaviour.

memcpy(pData,&id,sizeof id);/* using memcpy to copy */

Moreover the following line may cause problem if some day the size of your variables are more than 8. Change these also to sizeof

unsigned char* pData = new unsigned char[2 * sizeof (unsigned long)];
...
pData = pData + sizeof id;  // etc
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
1

On Windows, mostly for backward compatibility reasons, sizeof(long) is 4 even on 64 bit. On linux sizeof(long) in x86-64 (the platform you're probably using) is instead 8 bytes.

6502
  • 112,025
  • 15
  • 165
  • 265
1

use sizeof() instead of 4 in your program.

Madhu Kumar Dadi
  • 695
  • 8
  • 25
1

unsigned long is different size if you are using different operating system.

On 32 bit machines, usually unsigned long is 32 bit (4 bytes).
On 64 bit, usually unsigned long is 64 bit (8 bytes).

On top of that, it depends what is the C/C++ compiler. E.g. What is true for some compiler, might be not true for another.

Last I do not see where you release the memory you allocated with new.

Here is your code using sizeof():

#include <iostream>

#include <string.h>

int main(){
    unsigned long id = 12;
    unsigned long age = 14;
    size_t size = sizeof(unsigned long);
    unsigned char* pData = new unsigned char[2*size];

    memcpy(pData, &id, size);/* using memcpy to copy */

    pData = pData + size;

    memcpy(pData, &age, size);/* using memcpy to copy */

    std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

    pData = pData - size;

    std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

    // do you need to release the dynamic memory?
    delete pData;

    return 0;
}

Hope this helps. Comment if I miss something.

UPDATE:

I seems to missread the code. I am updated the code.

I will give you updated version where pointer arithmetic is used:

#include <iostream>

#include <string.h>

int main(){
    unsigned long id = 12;
    unsigned long age = 14;

    unsigned long* pData = new unsigned long[2];

    memcpy(pData, &id, sizeof(unsigned long));/* using memcpy to copy */

    pData++;

    memcpy(pData, &age, sizeof(unsigned long));/* using memcpy to copy */

    std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

    pData--;

    std::cout<<*reinterpret_cast<unsigned long*>(pData)<<std::endl;

    // do you need to release the dynamic memory?
    delete pData;

    return 0;
}

If I was you, I would do it like this - e.g. no sizeof, no & (address of).

#include <iostream>

#include <string.h>

int main(){
    unsigned long id = 12;
    unsigned long age = 14;

    unsigned long *pData = new unsigned long[2];

    pData[0] = id;
    pData[1] = age;

    std::cout << pData[1] << std::endl;

    std::cout << pData[0] << std::endl;

    delete pData;

    return 0;
}

Hope this helps. Comment if I miss something.

I saw the comment for Windows / Microsoft C++ and size of unsigned long. This might be true, but I still think sizeof() is the way to do it. With sizeof() code is more portable and might compile to different platform, even on platforms you have no knowledge about.

Nick
  • 9,962
  • 4
  • 42
  • 80
  • thanks for reply. size_t size = sizeof(unsigned long); unsigned char* pData = new unsigned char[2*size]; and second value is not coming proper. – abhi312 Jun 30 '15 at 06:34
  • 1
    wrong. `long` is always 32 bits on Windows, even 64-bit windows – phuclv Jun 30 '15 at 06:49
  • @LưuVĩnhPhúc you might be right, but I believe correct way is still with sizeof. Because under Linux or OSX or Digital Unix or HPUX situation might be different. – Nick Jun 30 '15 at 10:00