Expression evaluation using __int64

J

Jeff Bean

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_index) + 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
 
C

Carl Daniel [VC++ MVP]

Jeff said:
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_index) + 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
 
D

Doug Harrison [MVP]

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.
 
J

Jeff Bean

Carl Daniel said:
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: (e-mail address removed)
 
B

Ben Voigt [C++ MVP]

Jeff Bean said:
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.
 
D

Doug Harrison [MVP]

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 "conversions"
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top