macro help

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • inftoconc@gmail.com

    #1

    macro help

    Hi all,

    I wrote a macro to read 8 bytes from a byte stream. Am not
    sure if it is working ok. Can anyone please point out if there looks
    to be a problem!

    #define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
    + ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
    +4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
    8) + ( *(b+7))

    Here b is a pointer to an unsigned char.

    Thanks,

    Vishal

  • Ian Collins

    #2
    Re: macro help

    inftoconc@gmail .com wrote:
    Hi all,
    >
    I wrote a macro to read 8 bytes from a byte stream. Am not
    sure if it is working ok. Can anyone please point out if there looks
    to be a problem!
    >
    What did your test cases show you?
    #define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
    + ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
    +4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
    8) + ( *(b+7))
    >
    Why on Earth did you write a totally horrible macro when a function can
    do the job and is a kinder on the eye and debugger?

    --
    Ian Collins.

    Comment

    • Army1987

      #3
      Re: macro help

      On Sun, 30 Sep 2007 09:26:36 +0000, inftoconc wrote:
      Hi all,
      >
      I wrote a macro to read 8 bytes from a byte stream. Am not
      sure if it is working ok. Can anyone please point out if there looks
      to be a problem!
      >
      #define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
      + ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
      +4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
      8) + ( *(b+7))
      >
      Here b is a pointer to an unsigned char.
      1. The syntax of the cast is (type-name)cast-expression, e.g.
      (uint64_t)*b, not uint64_t(*b). Maybe you were thinking about C++?
      2. What's wrong with good ol' b[0], b[1] etc.? They're somewhat
      clearer than (*(b+1)).

      Try:
      #define READ64(b) ( ((uint64_t)(b)[0] << 56) + ((uint64_t)(b)[1] << 48) +\
      ((uint64_t)(b)[2] << 40) + etc... )
      (Also, if you're ever going to port this to somewhere CHAR_BIT 8
      you should mask each addend with & 0xFF, and if you aren't you
      could add #if CHAR_BIT != 8
      #error something
      #endif
      somewhere.)
      --
      Army1987 (Replace "NOSPAM" with "email")
      A hamburger is better than nothing.
      Nothing is better than eternal happiness.
      Therefore, a hamburger is better than eternal happiness.

      Comment

      • Army1987

        #4
        Re: macro help

        On Sun, 30 Sep 2007 04:14:19 -0700, William Pursell wrote:
        On 30 Sep, 10:26, inftoc...@gmail .com wrote:
        > I wrote a macro to read 8 bytes from a byte stream. Am not
        >sure if it is working ok. Can anyone please point out if there looks
        >to be a problem!
        >>
        >#define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
        >+ ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
        >+4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
        >8) + ( *(b+7))
        >>
        >Here b is a pointer to an unsigned char.
        >
        Lots of problems:
        >
        The endianness of the machine will have
        an impact, certainly.
        I think he did that to have the same format on all machines.
        Otherwise he could use memcpy().
        --
        Army1987 (Replace "NOSPAM" with "email")
        A hamburger is better than nothing.
        Nothing is better than eternal happiness.
        Therefore, a hamburger is better than eternal happiness.

        Comment

        • Chris Torek

          #5
          Re: macro help

          In article <46ff902c$0$159 55$426a74cc@new s.free.fr>
          Charlie Gordon <news@chqrlie.o rgwrote:
          >You SHOULD use a function for this, possibly an inline function.
          Indeed, in some cases it turns out to be faster to call a regular
          (non-inline) function than to do the code in line (either with a
          macro, or with an inline function). (As always, the way to find
          out is to measure it. If you do a lot of these conversions, it
          may be worth looking at your compiler's output. Many of today's
          ILP32-LL64 compilers produce poor 64-bit shift-and-mask code, so
          this sort of micro-optimization is occasionally worthwhile.)
          >Function:
          >
          >static inline uint64_t read64(unsigned char const *b) {
          return ((uint64_t)b[0] << 56) | ((uint64_t)b[1] << 48) |
          ((uint64_t)b[2] << 40) | ((uint64_t)b[3] << 32) |
          ((uint64_t)b[4] << 24) | ((uint64_t)b[5] << 16) |
          ((uint64_t)b[6] << 8) | ((uint64_t)b[7] << 0);
          >}
          >
          >If your compiler is not too smart, this might be better:
          >
          >static inline uint64_t read64(unsigned char const *b) {
          return ((uint64_t)(((u int32_t)b[0] << 24) | ((uint32_t)b[1] << 16) |
          ((uint32_t)b[2] << 8) | b[3]) << 32) |
          (((uint32_t)b[4] << 24) | ((uint32_t)b[5] << 16) |
          ((uint32_t)b[6] << 8) | b[7]);
          >}
          I find that applications that do this tend also to do 16 and/or
          32-bit numbers, so for the second case, consider, e.g.:

          static inline uint32_t read32(const unsigned char *b) {
          return ((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) |
          ((unsigned)b[2] << 8) | b[3];
          }
          static inline uint64_t read64(const unsigned char *b) {
          return ((uint64_t)read 32(b) << 32) | read32(b + 4);
          }

          One might also consider also using "unsigned long" and "unsigned
          long long" instead of the (possibly overspecified) uint32_t and
          uint64_t aliases; and read32 can call read16() twice, and read16()
          can use plain "unsigned int" (as the code in read32 above shows).
          --
          In-Real-Life: Chris Torek, Wind River Systems
          Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
          email: forget about it http://web.torek.net/torek/index.html
          Reading email is like searching for food in the garbage, thanks to spammers.

          Comment

          • Charlie Gordon

            #6
            Re: macro help

            "Thad Smith" <ThadSmith@acm. orga écrit dans le message de news:
            47004884$0$9042 1$892e0abb@auth .newsreader.oct anews.com...
            William Pursell wrote:
            >On 30 Sep, 10:26, inftoc...@gmail .com wrote:
            >> I wrote a macro to read 8 bytes from a byte stream. Am not
            >>sure if it is working ok. Can anyone please point out if there looks
            >>to be a problem!
            >>>
            >>#define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
            >>+ ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
            >>+4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
            >>8) + ( *(b+7))
            >>>
            >>Here b is a pointer to an unsigned char.
            >>
            >
            >What if a caller wants chars 2 through 9 from a buffer
            >and calls the macro as:
            >uint64_t x = READ64( b+2 );
            >
            It works properly. It would, however, fail with arguments such as b+1<<2.
            No, you are mistaken: it does not work for b+2 either. It compiles, but
            does not behave as intended. The MSB is read from b[0] and offset by 2.

            --
            Chqrlie.


            Comment

            • Charlie Gordon

              #7
              Re: macro help

              "Charlie Gordon" <news@chqrlie.o rga écrit dans le message de news:
              4700cef6$0$7288 $426a34cc@news. free.fr...
              "Thad Smith" <ThadSmith@acm. orga écrit dans le message de news:
              47004884$0$9042 1$892e0abb@auth .newsreader.oct anews.com...
              >William Pursell wrote:
              >>On 30 Sep, 10:26, inftoc...@gmail .com wrote:
              >>> I wrote a macro to read 8 bytes from a byte stream. Am not
              >>>sure if it is working ok. Can anyone please point out if there looks
              >>>to be a problem!
              >>>>
              >>>#define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
              >>>+ ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
              >>>+4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
              >>>8) + ( *(b+7))
              >>>>
              >>>Here b is a pointer to an unsigned char.
              >>>
              >>
              >>What if a caller wants chars 2 through 9 from a buffer
              >>and calls the macro as:
              >>uint64_t x = READ64( b+2 );
              >>
              >It works properly. It would, however, fail with arguments such as
              >b+1<<2.
              >
              No, you are mistaken: it does not work for b+2 either. It compiles, but
              does not behave as intended. The MSB is read from b[0] and offset by 2.
              Actually, it might compile as C++, but one has to fix the cast syntax for it
              to compile as C ;-)

              Complete answers have been posted on a different thread.

              --
              Chqrlie.


              Comment

              • Thad Smith

                #8
                Re: macro help

                Charlie Gordon wrote:
                "Charlie Gordon" <news@chqrlie.o rga écrit dans le message de news:
                4700cef6$0$7288 $426a34cc@news. free.fr...
                >"Thad Smith" <ThadSmith@acm. orga écrit dans le message de news:
                >47004884$0$904 21$892e0abb@aut h.newsreader.oc tanews.com...
                >>William Pursell wrote:
                >>>On 30 Sep, 10:26, inftoc...@gmail .com wrote:
                >>>> I wrote a macro to read 8 bytes from a byte stream. Am not
                >>>>sure if it is working ok. Can anyone please point out if there looks
                >>>>to be a problem!
                >>>>>
                >>>>#define READ64(b) ( (uint64_t(*b)) << 56) + ((uint64_t(*(b+ 1))) << 48)
                >>>>+ ((uint64_t(*(b+ 2))) << 40) +((uint64_t(*(b +3))) << 32)+((uint64_t( *(b
                >>>>+4))) << 24) + (( uint64_t(*(b+5) )) << 16) + (( uint64_t(*(b+6) )) <<
                >>>>8) + ( *(b+7))
                >>>>>
                >>>>Here b is a pointer to an unsigned char.
                >>>What if a caller wants chars 2 through 9 from a buffer
                >>>and calls the macro as:
                >>>uint64_t x = READ64( b+2 );
                >>It works properly. It would, however, fail with arguments such as
                >>b+1<<2.
                >No, you are mistaken: it does not work for b+2 either. It compiles, but
                >does not behave as intended. The MSB is read from b[0] and offset by 2.
                >
                Actually, it might compile as C++, but one has to fix the cast syntax for it
                to compile as C ;-)
                Thanks for correcting my blunders!


                --
                Thad

                Comment

                Working...