About retrieve an arbitrary byte among four bytes of an int.

Discussion in 'C Programming' started by lovecreatesbeauty, Jan 14, 2006.

  1. /*

    It seems that when an int with width of four bytes is assigned to a one
    byte width char, the first three bytes from left to right are discarded
    and the rightest byte is assigned to that char.

    So, I can just assign an int to a char to retrieve the rightest byte of
    that int, and I also use this method plus right-shift operation to get
    the leftest byte of an int.

    I should be wrong on it, please correct me with your expertise.

    Thank you

    lovecreatesbeauty

    */

    #include <stdio.h>

    int main(void)
    {
    unsigned int data = 'chum';
    unsigned char left = '\0';
    unsigned char right = '\0';

    printf("data: %#X\n", data);

    /* get the leftest byte of an int */
    left = data >> (sizeof(int) - 1) * 8;

    /* get the rightest byte of an int */
    right = data;

    printf("left: %#X, %c\n", left, left);
    printf("right: %#X, %c\n", right, right);

    return 0;
    }

    /* result: (Win2k, mingw32)
    data: 0X6368756D
    left: 0X63, c
    right: 0X6D, m
    */
     
    lovecreatesbeauty, Jan 14, 2006
    #1
    1. Advertising

  2. lovecreatesbeauty

    Eric Sosman Guest

    lovecreatesbeauty wrote:

    > /*
    >
    > It seems that when an int with width of four bytes is assigned to a one
    > byte width char, the first three bytes from left to right are discarded
    > and the rightest byte is assigned to that char.


    That's how it usually works out. From the language's
    point view you're assigning values rather than chunks of
    the representation, and the value stored in the char is
    derived from the value of the int via a conversion.

    Your example code uses unsigned ints and chars, for
    which things will work as you describe. For signed variants
    the question of representation comes into play, and things
    could turn out differently on a system that doesn't use
    two's complement arithmetic. Such systems are surpassingly
    rare nowadays, but ...

    > So, I can just assign an int to a char to retrieve the rightest byte of
    > that int, and I also use this method plus right-shift operation to get
    > the leftest byte of an int.


    Yes, for unsigned types. Be warned that negative integers
    do not right-shift the same way on all systems.

    > I should be wrong on it, please correct me with your expertise.
    >
    > Thank you
    >
    > lovecreatesbeauty
    >
    > */
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > unsigned int data = 'chum';


    This construct isn't portable, and the value assigned
    to data is entirely compiler-defined. Either the 'c' or
    the 'm' -- or even neither! -- might wind up in the low-
    order byte of data. A portable (assuming four-byte int)
    way of ensuring the order you expect is to assemble it
    from the individual pieces:

    unsigned int data = ('c' << 24) + ('h' << 16)
    + ('u' << 8) + 'm';

    > unsigned char left = '\0';
    > unsigned char right = '\0';
    >
    > printf("data: %#X\n", data);
    >
    > /* get the leftest byte of an int */
    > left = data >> (sizeof(int) - 1) * 8;


    This is fine, assuming eight-bit char. Machines
    with other char sizes are rare, but definitely do exist
    (they are commoner than machines that don't use two's
    complement). To gain more portability, you could #include
    the <limits.h> header and use CHAR_BIT instead of 8 (and
    you'd make similar adjustments in the initialization of
    data, above).

    > /* get the rightest byte of an int */
    > right = data;
    >
    > printf("left: %#X, %c\n", left, left);
    > printf("right: %#X, %c\n", right, right);
    >
    > return 0;
    > }
    >
    > /* result: (Win2k, mingw32)
    > data: 0X6368756D
    > left: 0X63, c
    > right: 0X6D, m
    > */


    A little thought will show that shifting by other
    amounts can retrieve the 'h' and 'u' characters, too.
    In fact, you can retrieve groups of bits that straddle
    the char boundaries, if you want. See also "masking."

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 14, 2006
    #2
    1. Advertising

  3. In article <>,
    lovecreatesbeauty <> wrote:
    >It seems that when an int with width of four bytes is assigned to a one
    >byte width char, the first three bytes from left to right are discarded
    >and the rightest byte is assigned to that char.


    What are "left" and "right" with respect to int?
    The byte order of int in a variable is unspecified, and the
    byte order of int in a CPU register might be different.

    Your example is for "Win32", which (if I understand correctly) is
    an OS implemented only for instruction sets that happen not to use
    "bigendian" storage order in memory, and whose CPU registers are not
    necessarily the same as their memory storage order.

    If you define "left" as Most Significant Bit and "right" as
    Least Signficant Bit, and the byte you want to get out is
    the one containing the Least Significant Bits, and you recognize
    that you are talking about *values* rather than about what might
    happen to be stored in memory, and if you are use 'unsigned'
    for the int and the char, and your int is 4 bytes, then Yes, a
    simple assignment is certain to have that result.


    >So, I can just assign an int to a char to retrieve the rightest byte of
    >that int, and I also use this method plus right-shift operation to get
    >the leftest byte of an int.


    You have jumped here from "when an int with of width four bytes" to
    "so I can just" make that assignment for the desired result. The
    problem with that is that for a random machine, int might not
    have a width of -four- bytes. You have taken behaviour that is
    true on one machine and generalized it to be true on all machines.
    --
    "It is important to remember that when it comes to law, computers
    never make copies, only human beings make copies. Computers are given
    commands, not permission. Only people can be given permission."
    -- Brad Templeton
     
    Walter Roberson, Jan 14, 2006
    #3
  4. Walter Roberson wrote:
    > In article <>,
    > What are "left" and "right" with respect to int?
    > The byte order of int in a variable is unspecified, and the
    > byte order of int in a CPU register might be different.
    >


    Yes, thank you. I'm a superficial guy with little knowledge.

    >
    > then Yes, a
    > simple assignment is certain to have that result.
    >


    Thank you again, but it's not a homework.

    lovecreatesbeauty
     
    lovecreatesbeauty, Jan 14, 2006
    #4
  5. "lovecreatesbeauty" <> writes:
    > Walter Roberson wrote:
    >> In article <>,
    >> What are "left" and "right" with respect to int?
    >> The byte order of int in a variable is unspecified, and the
    >> byte order of int in a CPU register might be different.

    >
    > Yes, thank you. I'm a superficial guy with little knowledge.
    >
    >> then Yes, a
    >> simple assignment is certain to have that result.

    >
    > Thank you again, but it's not a homework.


    He meant "assignment" as in "x=y;", not as in "homework assignment".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 14, 2006
    #5
  6. Eric Sosman <> writes:
    > lovecreatesbeauty wrote:
    >> /*
    >> It seems that when an int with width of four bytes is assigned to a
    >> one
    >> byte width char, the first three bytes from left to right are discarded
    >> and the rightest byte is assigned to that char.

    >
    > That's how it usually works out. From the language's
    > point view you're assigning values rather than chunks of
    > the representation, and the value stored in the char is
    > derived from the value of the int via a conversion.
    >
    > Your example code uses unsigned ints and chars, for
    > which things will work as you describe. For signed variants
    > the question of representation comes into play, and things
    > could turn out differently on a system that doesn't use
    > two's complement arithmetic. Such systems are surpassingly
    > rare nowadays, but ...


    The semantics of assigning a large value to an unsigned type too small
    to hold it are well defined. The result is effectively to discard the
    high-order bits (though it's defined in terms of the mathematical
    values, not in terms of representation).

    Assigning an overly large value to a *signed* type yields an
    implementation-defined result (or, in C99, raises an
    implementation-defined signal). It typically discards the high-order
    bits, but there are other possibilities; for example, saturation
    (converting all large values to the maximum value of the target type)
    is legal. You should usually just avoid doing that.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 14, 2006
    #6
  7. Walter Roberson wrote:
    > In article <>,
    > Your example is for "Win32", which (if I understand correctly) is
    > an OS implemented only for instruction sets that happen not to use
    > "bigendian" storage order in memory, and whose CPU registers are not
    > necessarily the same as their memory storage order.


    Thank you. I also tried this code snippet on a HP-UX 11i machine, the
    result is:

    $ cc +DAportable retrievebytefromint.c
    cc: "retrievebytefromint.c", line 5: warning 27: Integer character
    constant contains more than one character.
    $ a.out
    data: 0X6368756D
    left: 0X63, c
    right: 0X6D, m
    $

    lovecreatesbeauty
     
    lovecreatesbeauty, Jan 16, 2006
    #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,251
    Martien Verbruggen
    Jun 27, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,709
    Old Wolf
    Jan 20, 2004
  3. Graham Nicholls
    Replies:
    3
    Views:
    457
    Alex Martelli
    Aug 7, 2003
  4. William S. Huizinga

    Need elegant way to cast four bytes into a long

    William S. Huizinga, Aug 8, 2003, in forum: Python
    Replies:
    11
    Views:
    518
    Anton Vredegoor
    Aug 11, 2003
  5. Hahnemann

    Four or Two Bytes?

    Hahnemann, May 30, 2008, in forum: C Programming
    Replies:
    22
    Views:
    668
    Barry Schwarz
    Jun 2, 2008
Loading...

Share This Page