Expression evaluation using __int64

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeff Bean

    Expression evaluation using __int64

    I need to compute a 64 bit file offset which will get passed to the _lseeki64 function.

    The inputs to the offset calculation are all unsigned shorts or unsigned longs. For example:

    unsigned short page_size;
    unsigned long page_index;
    unsigned long page_offset;
    __int64 file_offset;
    file_offset = (page_size * page_index) + page_offset;

    I think that the above expression is subject to integer overflow, but I am not clear on how to
    ensure that the intermediate values in the expression are calculated using 64 bits. The topic on
    "Integral Promotions" in the VC++ Language Reference states the following:

    "C++ promotions are "value-preserving." That is, the value after the promotion is guaranteed to be
    the same as the value before the promotion. In value-preserving promotions, objects of shorter
    integral types (such as bit fields or objects of type char) are promoted to type int if int can
    represent the full range of the original type. If int cannot represent the full range of values,
    then the object is promoted to type unsigned int. Although this strategy is the same as that used by
    ANSI C, value-preserving conversions do not preserve the "signedness " of the object."

    The above paragraph is silent on what happens if one of the values is longer than an int. If I
    change the above expression to:

    file_offset = (page_size * (__int64)page_i ndex) + page_offset;

    does that guarantee that the intermediate value (page_size * (__int64)page) will be evaluated using
    64 bits? Are all intermediate values involving 64 bit integers also 64 bit integers?

    Jeff Bean
  • Carl Daniel [VC++ MVP]

    #2
    Re: Expression evaluation using __int64

    Jeff Bean wrote:
    I need to compute a 64 bit file offset which will get passed to the
    _lseeki64 function.
    >
    The inputs to the offset calculation are all unsigned shorts or
    unsigned longs. For example:
    >
    unsigned short page_size;
    unsigned long page_index;
    unsigned long page_offset;
    __int64 file_offset;
    file_offset = (page_size * page_index) + page_offset;
    >
    I think that the above expression is subject to integer overflow, but
    I am not clear on how to ensure that the intermediate values in the
    expression are calculated using 64 bits. The topic on "Integral
    Promotions" in the VC++ Language Reference states the following:
    >
    "C++ promotions are "value-preserving." That is, the value after the
    promotion is guaranteed to be the same as the value before the
    promotion. In value-preserving promotions, objects of shorter
    integral types (such as bit fields or objects of type char) are
    promoted to type int if int can represent the full range of the
    original type. If int cannot represent the full range of values, then
    the object is promoted to type unsigned int. Although this strategy
    is the same as that used by ANSI C, value-preserving conversions do
    not preserve the "signedness " of the object."
    >
    The above paragraph is silent on what happens if one of the values is
    longer than an int. If I change the above expression to:
    >
    file_offset = (page_size * (__int64)page_i ndex) + page_offset;
    >
    does that guarantee that the intermediate value (page_size *
    (__int64)page) will be evaluated using 64 bits? Are all intermediate
    values involving 64 bit integers also 64 bit integers?
    Yes. Casting either of the multiplicands as you've shown will guarantee
    that the entire expression is evaluated as 64 bit integers.

    -cd


    Comment

    • Doug Harrison [MVP]

      #3
      Re: Expression evaluation using __int64

      On Mon, 17 Sep 2007 23:10:33 -0700, "Carl Daniel [VC++ MVP]"
      <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pamwrote:
      >The above paragraph is silent on what happens if one of the values is
      >longer than an int. If I change the above expression to:
      >>
      >file_offset = (page_size * (__int64)page_i ndex) + page_offset;
      >>
      >does that guarantee that the intermediate value (page_size *
      >(__int64)pag e) will be evaluated using 64 bits? Are all intermediate
      >values involving 64 bit integers also 64 bit integers?
      >
      >Yes. Casting either of the multiplicands as you've shown will guarantee
      >that the entire expression is evaluated as 64 bit integers.
      This goes without saying, but since I once had to fix dozens of occurrences
      of this in some 16-bit code (with __int64 replaced by long), I'm gonna say
      it anyway. :) It's really important to put the cast in the right place; for
      example, this does *not* have the same effect:

      (__int64) (page_size * page_index) + page_offset // WRONG!

      For the multiplication to be performed at 64-bit precision, you must cast
      one of the factors, as Carl said, *not* the product.

      --
      Doug Harrison
      Visual C++ MVP

      Comment

      • Jeff Bean

        #4
        Re: Expression evaluation using __int64

        "Carl Daniel [VC++ MVP]" wrote:
        >Yes. Casting either of the multiplicands as you've shown will guarantee
        >that the entire expression is evaluated as 64 bit integers.
        Carl, Thank you for the quick answer. Do you know of some place in the MSDN library (or the C/C++
        standards) where I might have discovered for myself the rules for the width of intermediate values
        during expression evaluation?

        Jeff Bean
        Jeff Bean
        CWC Software
        Tel: (480) 596-9617
        Fax: (480) 443-0594
        Email: jeff@cwcsoftwar e.com

        Comment

        • Ben Voigt [C++ MVP]

          #5
          Re: Expression evaluation using __int64


          "Jeff Bean" <jeff@cwcsoft.c omwrote in message
          news:jl50f3ho54 aid21jos6ov6ida ttlnms7pg@4ax.c om...
          "Carl Daniel [VC++ MVP]" wrote:
          >
          >>Yes. Casting either of the multiplicands as you've shown will guarantee
          >>that the entire expression is evaluated as 64 bit integers.
          >
          Carl, Thank you for the quick answer. Do you know of some place in the
          MSDN library (or the C/C++
          standards) where I might have discovered for myself the rules for the
          width of intermediate values
          during expression evaluation?
          In the standard, this is primarily governed by 5.9, which states that
          expressions use promotions (widening, see 4.5) not conversions (narrowing,
          see 4.7), but vendor-specific types such as __int64 are not mentioned.
          >
          Jeff Bean
          Jeff Bean
          CWC Software
          Tel: (480) 596-9617
          Fax: (480) 443-0594
          Email: jeff@cwcsoftwar e.com

          Comment

          • Doug Harrison [MVP]

            #6
            Re: Expression evaluation using __int64

            On Tue, 18 Sep 2007 16:02:49 -0500, "Ben Voigt [C++ MVP]"
            <rbv@nospam.nos pamwrote:
            >In the standard, this is primarily governed by 5.9, which states that
            >expressions use promotions (widening, see 4.5) not conversions (narrowing,
            >see 4.7)
            Chapter 5, paragraph 9 talks about the "usual arithmetic conversions",
            which can involve both promotion and conversion. Note that "conversion s"
            aren't strictly narrowing; for example, int-to-long is a conversion, not a
            promotion. The term "promotion" means conversion of a (nominally) smaller
            type to int, unless int can't hold all the values of the smaller type, in
            which case, the conversion goes per 4.5.
            but vendor-specific types such as __int64 are not mentioned.
            It's inconceivable that a compiler vendor would purposely do the unexpected
            here and not extend the rules that govern built-in types to types such as
            __int64. MSDN doesn't mention __int64 in the obvious places in the "Visual
            C++ Language Reference", but that doesn't really bother me. I've always
            "just used" the type, and it's always worked as expected.

            --
            Doug Harrison
            Visual C++ MVP

            Comment

            Working...