Macro for setting MSB - Intended to work on both Little and Bigendian machines

Discussion in 'C Programming' started by Myth__Buster, Mar 26, 2013.

  1. Myth__Buster

    Myth__Buster Guest

    Hi All,

    Here is my attempt for setting the MSB of an integer depending upon whetherthe underlying machine is Little or Big-endian. Any comments/suggestions/views are appreciated.

    Here I have assumed though I don't store the 1LL(LL - long long - to force 1 to be stored in a multiple memory resource(say register) to hold the value 1) in a variable in my program, it will be accessed as a multi-byte valueand hence 1 will be stored in the LSB of most-significant-byte of the memory resource(say register) and not in the LSB of least-significant-byte of that resource. Please let me know if this is correct.

    Code:

    #include <stdio.h>
    #include <limits.h>

    #define LSET_MSB(x) ((x) = (x) | 1 << sizeof(x) * CHAR_BIT - 1)

    #define BSET_MSB(x) ((x) = (x) | 1 << CHAR_BIT - 1)

    #define LIITE_ENDIAN (1LL & 1)

    int main(void)
    {
    int x = 1;

    printf("x : %d\n", x);

    if ( LIITE_ENDIAN )
    {
    printf("Little\n");
    LSET_MSB(x);
    }
    else
    {
    printf("Big\n");
    BSET_MSB(x);
    }

    printf("x : %d\n", x);

    return 0;
    }


    Cheers,
    Raghavan
    Myth__Buster, Mar 26, 2013
    #1
    1. Advertising

  2. On Tue, 26 Mar 2013 00:46:39 -0700, Myth__Buster wrote:

    > Hi All,
    >
    > Here is my attempt for setting the MSB of an integer depending upon
    > whether the underlying machine is Little or Big-endian. Any
    > comments/suggestions/views are appreciated.
    >
    > Here I have assumed though I don't store the 1LL(LL - long long - to
    > force 1 to be stored in a multiple memory resource(say register) to hold
    > the value 1) in a variable in my program, it will be accessed as a
    > multi-byte value and hence 1 will be stored in the LSB of
    > most-significant-byte of the memory resource(say register) and not in
    > the LSB of least-significant-byte of that resource. Please let me know
    > if this is correct.


    If I understand correctly what you mean, then no, that is not correct.
    In C, you don't have to deal with endianness except in the very specific
    situation where, in your program, you have to convert a value of type X
    to a sequence of bytes in a particular endianness or vice versa.
    In particular, all arithmetic and bitwise operations are specified in
    such a way that the result does not depend in any way on how a type is
    split into bytes nor on how those bytes might be ordered in memory.

    >
    > Code:
    >
    > #include <stdio.h>
    > #include <limits.h>
    >
    > #define LSET_MSB(x) ((x) = (x) | 1 << sizeof(x) * CHAR_BIT - 1)


    This macro will set the most significant bit of x regardless of how large
    x is or how x is stored in memory.

    >
    > #define BSET_MSB(x) ((x) = (x) | 1 << CHAR_BIT - 1)


    This macro will set the most significant bit of the least significant
    byte of x regardless of how large x is or how x is stored in memory.

    >
    > #define LIITE_ENDIAN (1LL & 1)


    This macro is identical to
    #define LIITE_ENDIAN (1)
    It just tests is the values 1 and 1 have at least one bit set in common,
    which is true by definition.

    >
    > int main(void)
    > {
    > int x = 1;
    >
    > printf("x : %d\n", x);
    >
    > if ( LIITE_ENDIAN )
    > {
    > printf("Little\n");
    > LSET_MSB(x);
    > }
    > else
    > {

    If you set the warning level high enough, your compiler might even warn
    you that this branch can never be taken.

    > printf("Big\n");
    > BSET_MSB(x);
    > }
    >
    > printf("x : %d\n", x);
    >
    > return 0;
    > }
    >
    >
    > Cheers,
    > Raghavan


    Bart v Ingen Schenau
    Bart van Ingen Schenau, Mar 26, 2013
    #2
    1. Advertising

  3. Myth__Buster

    Myth__Buster Guest

    On Tuesday, March 26, 2013 4:51:33 AM UTC-4, Bart van Ingen Schenau wrote:
    > On Tue, 26 Mar 2013 00:46:39 -0700, Myth__Buster wrote:
    >
    >
    >
    > > Hi All,

    >
    > >

    >
    > > Here is my attempt for setting the MSB of an integer depending upon

    >
    > > whether the underlying machine is Little or Big-endian. Any

    >
    > > comments/suggestions/views are appreciated.

    >
    > >

    >
    > > Here I have assumed though I don't store the 1LL(LL - long long - to

    >
    > > force 1 to be stored in a multiple memory resource(say register) to hold

    >
    > > the value 1) in a variable in my program, it will be accessed as a

    >
    > > multi-byte value and hence 1 will be stored in the LSB of

    >
    > > most-significant-byte of the memory resource(say register) and not in

    >
    > > the LSB of least-significant-byte of that resource. Please let me know

    >
    > > if this is correct.

    >
    >
    >
    > If I understand correctly what you mean, then no, that is not correct.
    >
    > In C, you don't have to deal with endianness except in the very specific
    >
    > situation where, in your program, you have to convert a value of type X
    >
    > to a sequence of bytes in a particular endianness or vice versa.
    >
    > In particular, all arithmetic and bitwise operations are specified in
    >
    > such a way that the result does not depend in any way on how a type is
    >
    > split into bytes nor on how those bytes might be ordered in memory.
    >
    >
    >
    > >

    >
    > > Code:

    >
    > >

    >
    > > #include <stdio.h>

    >
    > > #include <limits.h>

    >
    > >

    >
    > > #define LSET_MSB(x) ((x) = (x) | 1 << sizeof(x) * CHAR_BIT - 1)

    >
    >
    >
    > This macro will set the most significant bit of x regardless of how large
    >
    > x is or how x is stored in memory.
    >
    >
    >
    > >

    >
    > > #define BSET_MSB(x) ((x) = (x) | 1 << CHAR_BIT - 1)

    >
    >
    >
    > This macro will set the most significant bit of the least significant
    >
    > byte of x regardless of how large x is or how x is stored in memory.
    >
    >
    >
    > >

    >
    > > #define LIITE_ENDIAN (1LL & 1)

    >
    >
    >
    > This macro is identical to
    >
    > #define LIITE_ENDIAN (1)
    >
    > It just tests is the values 1 and 1 have at least one bit set in common,
    >
    > which is true by definition.
    >
    >
    >
    > >

    >
    > > int main(void)

    >
    > > {

    >
    > > int x = 1;

    >
    > >

    >
    > > printf("x : %d\n", x);

    >
    > >

    >
    > > if ( LIITE_ENDIAN )

    >
    > > {

    >
    > > printf("Little\n");

    >
    > > LSET_MSB(x);

    >
    > > }

    >
    > > else

    >
    > > {

    >
    > If you set the warning level high enough, your compiler might even warn
    >
    > you that this branch can never be taken.
    >
    >
    >
    > > printf("Big\n");

    >
    > > BSET_MSB(x);

    >
    > > }

    >
    > >

    >
    > > printf("x : %d\n", x);

    >
    > >

    >
    > > return 0;

    >
    > > }

    >
    > >

    >
    > >

    >
    > > Cheers,

    >
    > > Raghavan

    >
    >
    >
    > Bart v Ingen Schenau


    Hi,

    Well, I had to edit my question couple of times. Here is the correct one - https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.c/5jgv9EqggKI
    Please follow there.

    Cheers.
    Myth__Buster, Mar 26, 2013
    #3
  4. Myth__Buster

    Les Cargill Guest

    Bart van Ingen Schenau wrote:
    > On Tue, 26 Mar 2013 00:46:39 -0700, Myth__Buster wrote:
    >
    >> Hi All,
    >>
    >> Here is my attempt for setting the MSB of an integer depending upon
    >> whether the underlying machine is Little or Big-endian. Any
    >> comments/suggestions/views are appreciated.
    >>
    >> Here I have assumed though I don't store the 1LL(LL - long long - to
    >> force 1 to be stored in a multiple memory resource(say register) to hold
    >> the value 1) in a variable in my program, it will be accessed as a
    >> multi-byte value and hence 1 will be stored in the LSB of
    >> most-significant-byte of the memory resource(say register) and not in
    >> the LSB of least-significant-byte of that resource. Please let me know
    >> if this is correct.

    >
    > If I understand correctly what you mean, then no, that is not correct.
    > In C, you don't have to deal with endianness except in the very specific
    > situation where, in your program, you have to convert a value of type X
    > to a sequence of bytes in a particular endianness or vice versa.


    The "specific situation" is almost always
    described as "needing to conform to network byte order".

    > In particular, all arithmetic and bitwise operations are specified in
    > such a way that the result does not depend in any way on how a type is
    > split into bytes nor on how those bytes might be ordered in memory.
    >

    <snip>

    --
    Les Cargill
    Les Cargill, Mar 26, 2013
    #4
  5. Re: Macro for setting MSB - Intended to work on both Little and Big endian machines

    Myth__Buster <> writes:
    [...]
    > Well, I had to edit my question couple of times. Here is the correct
    > one -
    > https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.c/5jgv9EqggKI
    > Please follow there.


    You're posting to Usenet via the Google Groups interface.
    Google does some things well, but their Usenet interface is not
    one of them. Most of us read this newsgroup using NNTP-capable
    newsreader programs, which have nothing to do with Google.

    Some guidelines for posting here (which GG makes unnecessarily
    difficult):

    Keep your lines under 80 columns, preferably under 72. Not all
    newsreader programs deal with with very long lines. (Mine, for
    example, doesn't wrap at word boundaries.)

    When posting a followup, quote the previous article, but only
    enough of it for your followup to make sense. GG has a bug that
    causes it to double-space quoted text. Consider copy-and-pasting
    your post into a text editor, cleaning it up, and copy-and-pasting
    it back to your web browser before posting.

    You can't edit a post once you've hit "send" (or whatever your
    equivalent is); you can only post a new article or a followup.
    Don't change the subject line unnecessarily. If you need to correct
    an article, do it as a followup.

    Consider getting an actual newsreader program (I use Gnus, which
    runs under Emacs; Mozilla Thunderbird also works) and an account
    on a news server (I use news.eternal-september.org, which is free
    and works pretty well).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Mar 26, 2013
    #5
  6. Re: Macro for setting MSB - Intended to work on both Little and Big endian machines

    Les Cargill <> wrote:
    > Bart van Ingen Schenau wrote:

    (snip)
    >> In C, you don't have to deal with endianness except in the very specific
    >> situation where, in your program, you have to convert a value of type X
    >> to a sequence of bytes in a particular endianness or vice versa.


    > The "specific situation" is almost always
    > described as "needing to conform to network byte order".


    In that case, something like:

    if(ntohl(1)==1)

    should work. (With the appropriate #include file.)

    -- glen
    glen herrmannsfeldt, Mar 26, 2013
    #6
  7. Myth__Buster

    Jorgen Grahn Guest

    On Tue, 2013-03-26, Bart van Ingen Schenau wrote:
    ....
    > In C, you don't have to deal with endianness except in the very specific
    > situation where, in your program, you have to convert a value of type X
    > to a sequence of bytes in a particular endianness or vice versa.


    And even then you don't have to deal with endianness in the sense of
    "what's the internal structure of an int?". Untested example:

    void put16_bigendian(unsigned n, uint8_t* dest)
    {
    *dest++ = n >> 8;
    *dest++ = n;
    }

    Certain APIs /force/ you to deal with it, e.g. the BSD socket API
    which gives you IP addresses and UDP or TCP port numbers as
    big-endian quantities.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Mar 26, 2013
    #7
  8. Myth__Buster

    Martin Shobe Guest

    On 3/26/2013 3:51 AM, Bart van Ingen Schenau wrote:
    > On Tue, 26 Mar 2013 00:46:39 -0700, Myth__Buster wrote:
    >>
    >> #define LSET_MSB(x) ((x) = (x) | 1 << sizeof(x) * CHAR_BIT - 1)

    >
    > This macro will set the most significant bit of x regardless of how large
    > x is or how x is stored in memory.


    As far as I can tell, this would encounter undefined behavior if 1 <<
    sizeof(x) * CHAR_BIT - 1 exceeds INT_MAX, which will happen if sizeof(x)
    >= sizeof(int).


    Better would be to use

    #include <stdint.h>

    #define LSET_MSB(x) ((x) = (x) | (uintmax_t) 1 << sizeof(x) * CHAR_BIT - 1)

    Martin Shobe
    Martin Shobe, Mar 26, 2013
    #8
  9. Myth__Buster

    Correador UK Guest

    On 26 Mar, 19:04, Martin Shobe <> wrote:
    > On 3/26/2013 3:51 AM, Bart van Ingen Schenau wrote:
    >
    > > On Tue, 26 Mar 2013 00:46:39 -0700, Myth__Buster wrote:

    >
    > >> #define LSET_MSB(x) ((x) = (x) | 1 << sizeof(x) * CHAR_BIT - 1)

    >
    > > This macro will set the most significant bit of x regardless of how large
    > > x is or how x is stored in memory.

    >
    > As far as I can tell, this would encounter undefined behavior if 1 <<
    > sizeof(x) * CHAR_BIT - 1 exceeds INT_MAX, which will happen if sizeof(x)
    >  >= sizeof(int).
    >
    > Better would be to use
    >
    > #include <stdint.h>
    >
    > #define LSET_MSB(x) ((x) = (x) | (uintmax_t) 1 << sizeof(x) * CHAR_BIT - 1)


    I'd consider using (INT_MAX >> 1) + 1 as a way to get the MSB. No
    worries about overflow, sizes or padding bits.
    Correador UK, Mar 27, 2013
    #9
    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. Myth__Buster
    Replies:
    0
    Views:
    153
    Myth__Buster
    Mar 26, 2013
  2. Myth__Buster
    Replies:
    0
    Views:
    155
    Myth__Buster
    Mar 26, 2013
  3. Myth__Buster
    Replies:
    0
    Views:
    159
    Myth__Buster
    Mar 26, 2013
  4. Myth__Buster
    Replies:
    1
    Views:
    160
    Eric Sosman
    Mar 26, 2013
  5. Myth__Buster
    Replies:
    16
    Views:
    358
    glen herrmannsfeldt
    Mar 26, 2013
Loading...

Share This Page