Putting an int value in a char array

Discussion in 'C Programming' started by Vlad Dogaru, May 2, 2008.

  1. Vlad Dogaru

    Vlad Dogaru Guest

    Hi everyone,

    I'm trying to reliably store and read back an int (or short) into/from
    a character array. How does one do this in C? I've thought about using
    bit shifting and the like in order to put one char at a time, but this
    doesn't seem right. Is there something I'm missing? If it's any help,
    I'm trying to build a char array to send through a socket.

    Thanks,
    Vlad
    Vlad Dogaru, May 2, 2008
    #1
    1. Advertising

  2. Vlad Dogaru <> writes:

    > I'm trying to reliably store and read back an int (or short) into/from
    > a character array. How does one do this in C?


    memcpy(&char_buf, &int_var, sizeof int_var);

    > I've thought about using
    > bit shifting and the like in order to put one char at a time, but this
    > doesn't seem right. Is there something I'm missing? If it's any help,
    > I'm trying to build a char array to send through a socket.


    Ah! Well you have a better method then. The above, being a memory
    copy, is not right if you send data between systems with different byte
    orderings. The shifting method (used on unsigned types) can give you
    a portable solution.

    --
    Ben.
    Ben Bacarisse, May 2, 2008
    #2
    1. Advertising

  3. On May 2, 5:52 pm, Ben Bacarisse <> wrote:

    > Ah!  Well you have a better method then.  The above, being a memory
    > copy, is not right if you send data between systems with different byte
    > orderings.  The shifting method (used on unsigned types) can give you
    > a portable solution.



    Programs that do networking have functions to convert between "native
    byte order" and "network byte order". Network byte order happens to be
    big-endian, so on Motorolla machine it's a no-op, while on Intel
    machines the bytes have to be re-arranged.

    Your program should be able to play with bytes however it likes and
    then rely on the conversion function to send them out in Network Byte
    order.
    Tomás Ó hÉilidhe, May 2, 2008
    #3
  4. Vlad Dogaru

    Vlad Dogaru Guest

    On May 2, 7:52 pm, Ben Bacarisse <> wrote:
    > memcpy(&char_buf, &int_var, sizeof int_var);
    > [snip]
    > The shifting method (used on unsigned types) can give you
    > a portable solution.


    Would memcpy and htons & co be a correct approach? My problem is that
    it's not only short ints that I have to accomodate, but also the
    occasional long; I'd like to have a uniform handling of these
    operations.

    Also, I'm not sure if the way I found to "deserialize" these values is
    safe and recommended:

    x = htons(x);
    memcpy(&buffer, &x, sizeof x);
    /* Later, at the other end: */
    x = ntohs(*((unsigned short *) buffer));

    I only need unsigned values, so unsigned {short, long} should be
    enough. And one final question: would there be any reason to using
    uint16_t and uint32_t instead of unsigned short and unsigned long?

    Thanks and sorry for the question avalanche,
    Vlad
    Vlad Dogaru, May 3, 2008
    #4
  5. Vlad Dogaru

    Vlad Dogaru Guest

    On May 2, 8:43 pm, Joe Wright <> wrote:
    > Vlad Dogaru wrote:
    > > Hi everyone,

    >
    > > I'm trying to reliably store and read back an int (or short) into/from
    > > a character array. How does one do this in C? I've thought about using
    > > bit shifting and the like in order to put one char at a time, but this
    > > doesn't seem right. Is there something I'm missing? If it's any help,
    > > I'm trying to build a char array to send through a socket.

    >
    > sprintf() will do the int -> string thing.
    > strtol() will do the string to int.


    These are, indeed, a boon to programmers, but I need to send the
    numbers in binary format.

    Vlad
    Vlad Dogaru, May 3, 2008
    #5
  6. Vlad Dogaru <> writes:

    > On May 2, 7:52 pm, Ben Bacarisse <> wrote:
    >> memcpy(&char_buf, &int_var, sizeof int_var);
    >> [snip]
    >> The shifting method (used on unsigned types) can give you
    >> a portable solution.

    >
    > Would memcpy and htons & co be a correct approach?


    First htons and htnol (the "long" version) are POSIX, so technically
    off topic here. They are an excellent choice for this problem but
    they incur a cost that can be avoided if you are designing a system
    for CPUs where the "host" representation is different to the "network"
    one. If you can use you own functions, you can avoid this (probably
    small) cost by making these operations "null" on your main platform.

    > My problem is that
    > it's not only short ints that I have to accomodate, but also the
    > occasional long; I'd like to have a uniform handling of these
    > operations.


    Then there is htonl and ntohl that take uint32_t values. Note that C
    does not insist that long is 32 bits, but uint32_t is.

    > Also, I'm not sure if the way I found to "deserialize" these values is
    > safe and recommended:
    >
    > x = htons(x);
    > memcpy(&buffer, &x, sizeof x);


    That is the safe, portable, way. However, a lot of code will be able
    to define the buffer as struct with integer members, so one often
    sees:

    msg.data1 = htons(x);

    or even, the more dangerous:

    *(uint16_t *)buffer = htons(x);

    The memcpy version avoids any alignment problems and so it more portable.

    > /* Later, at the other end: */
    > x = ntohs(*((unsigned short *) buffer));


    The reverse would have been

    memcpy(&x, &buffer, sizeof x);
    x = htons(x);

    but the dangerous cast is often used. Data formats in protocols are
    often chosen so that there will be no alignment problems on most
    common processors, so you will have to decide between portability,
    code clarity and speed of packing knowing what you know about the
    target systems and the purpose of the code.

    > I only need unsigned values, so unsigned {short, long} should be
    > enough. And one final question: would there be any reason to using
    > uint16_t and uint32_t instead of unsigned short and unsigned long?


    Yes. The most important is that POSIX now defines the [nh]to[hn][ls]
    functions in terms of these types. These days, you are more likely
    to find a system where short > 16 bits or long > 32 bits than you are
    to find one where uint32_t is either not defined or is hard to define
    yourself.

    --
    Ben.
    Ben Bacarisse, May 3, 2008
    #6
  7. Vlad Dogaru

    Vlad Dogaru Guest

    On May 3, 5:01 pm, Ben Bacarisse <> wrote:
    > Yes. The most important is that POSIX now defines the [nh]to[hn][ls]
    > functions in terms of these types. These days, you are more likely
    > to find a system where short > 16 bits or long > 32 bits than you are
    > to find one where uint32_t is either not defined or is hard to define
    > yourself.


    Thank you for all your time, Ben.

    Vlad
    Vlad Dogaru, May 3, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,199
    Martien Verbruggen
    Jun 27, 2003
  2. trey

    newbie: char* int and char *int

    trey, Sep 10, 2003, in forum: C Programming
    Replies:
    7
    Views:
    397
    Irrwahn Grausewitz
    Sep 10, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,615
    Old Wolf
    Jan 20, 2004
  4. lovecreatesbeauty
    Replies:
    1
    Views:
    1,015
    Ian Collins
    May 9, 2006
  5. gert
    Replies:
    20
    Views:
    1,144
Loading...

Share This Page