Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / November 2004

Tip: Looking for answers? Try searching our database.

Problem with VC++ signed and unsigned __int64 << and >> operators?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Peter Bromley - 21 Nov 2004 21:35 GMT
The following code snippet does not seem to work correcly

unsigned __int64 result = 0xFFFFFFFFFFFFFFFF;
result = result << 64;
Debugger.WriteLine(System::String::Format(S"{0:X16}", __box(result));
result = 0xFFFFFFFFFFFFFFFF;
result = result >> 64;
Debugger.WriteLine(System::String::Format(S"{0:X16}", __box(result));

__int64 result = -1;
result = result << 64;
Debugger.WriteLine(System::String::Format(S"{0:X16}", __box(result));

I am expecting output to read

0000000000000000
FFFFFFFFFFFFFFFF
0000000000000000
FFFFFFFFFFFFFFFF

but output reads

FFFFFFFF00000000    << incorrect
00000000FFFFFFFF    << incorrect
FFFFFFFF00000000    << incorrect
FFFFFFFFFFFFFFFF    << correct

All other shift values ( < 64) appear to work correctly.

Can someone from MS confirm this is a bug with the int64 shift
operators, please?

Peter

Signature

If you wish to reply to me directly, my addres is spam proofed as:

pbromley at adi dot co dot nz

Or if you prefer - nospam@nowhere.com  :-)

Doug Harrison [MVP] - 21 Nov 2004 22:30 GMT
>The following code snippet does not seem to work correcly
>
[quoted text clipped - 24 lines]
>
>All other shift values ( < 64) appear to work correctly.

It's undefined to shift a value by an amount >= its length in bits, so you
need to avoid doing that.

Signature

Doug Harrison
Microsoft MVP - Visual C++

Gabest - 22 Nov 2004 03:17 GMT
> It's undefined to shift a value by an amount >= its length in bits, so you
> need to avoid doing that.

This thru for mc++ only, right? Shifting in x86 is well defined, for
unsigned 0s are shifted in, for signed the sign bit is extended when needed.
I wonder what can be the reason why the same code compiled for .net
shouldn't give the same results as its native counterpart.
Gabest - 22 Nov 2004 03:21 GMT
>> It's undefined to shift a value by an amount >= its length in bits, so
>> you
>> need to avoid doing that.
>
> This thru

"is true" I mean. It's really late here :)
Carl Daniel [VC++ MVP] - 22 Nov 2004 03:33 GMT
>> It's undefined to shift a value by an amount >= its length in bits,
>> so you need to avoid doing that.
[quoted text clipped - 3 lines]
> needed. I wonder what can be the reason why the same code compiled
> for .net shouldn't give the same results as its native counterpart.

No, it's true for C and C++ in general - shifting by an amount >= the
variable size is undefined behavior according to the standards.

-cd
Gabest - 22 Nov 2004 03:41 GMT
Well, after digging up intel's manual on these shifting instructions, it is
defined but not in the way I though to be:

"The count operand can be an immediate value or register CL. The count is
masked to 5 bits, which limits the count range to 0 to 31"

I believe amd can have something similar for the x86-64 ISA in its manuals
too, and also that in 32 bit mode the compiler inserts such a piece of code
what still gives a good result for its builtin __int64 type, but only for
the native code.
Hendrik Schober - 23 Nov 2004 13:34 GMT
> Well, after digging up intel's manual on these shifting instructions, it is
> defined but not in the way I though to be:
[quoted text clipped - 6 lines]
> what still gives a good result for its builtin __int64 type, but only for
> the native code.

 The problem is that you're not programming
 in assembler/machine code. If you're in
 C/C++/MC++ land, you have to follow the
 rules as spelled out there. For C++ (and
 most likely for C, too), what you do is
 undefined. As for MC++ -- I don't know
 that.

 Schobi

Signature

SpamTrap@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett

Gabest - 23 Nov 2004 14:20 GMT
>  The problem is that you're not programming
>  in assembler/machine code.

Yea, you are right, I was believing too much that the compiler would just
use the existing assembly instructions for shifting, while it has the right
to translate it to anything else of course.

There is still one thing but bothers me though. This means you cannot be
sure about shifting by a+b always gives the same result as shifting by a and
then b separately. Something like saying 1+2+3 equals to 6, but the result
of 1+5 is undefined. I can understand shl/shr/sar can have some limitations,
since they are just low level instructions translated directly to machine
code, but in c/c++ this sounds pretty wierd to me.

> If you're in
>  C/C++/MC++ land, you have to follow the
[quoted text clipped - 4 lines]
>
>  Schobi
Bo Persson - 23 Nov 2004 17:41 GMT
>>  The problem is that you're not programming
>>  in assembler/machine code.
>
> Yea, you are right, I was believing too much that the compiler would
> just use the existing assembly instructions for shifting, while it has
> the right to translate it to anything else of course.

But the limitations are there just so that the compiler should be able
to use the machine instructions.  :-)

On recent x86 machines, the shift count is limited to be less than the
number of bits in a machine register. On other processors it is not. So,
the C and C++ standards conveniently state that we cannot know what will
happen - undefined behavior.

On early x86 processors, there was no specific limit on the shift count,
but also no limit on how long it would take to execute. Luckily they
were limited to 16 bits. Now consider a 32 bit model, where

1 << UINT_MAX;

would actually shift the bit left 4 billion times. How long would that
take? What would the interrupt response time be like during the
shifting?

Bo Persson
Gabest - 24 Nov 2004 01:48 GMT
> 1 << UINT_MAX;
>
> would actually shift the bit left 4 billion times. How long would that
> take? What would the interrupt response time be like during the shifting?

Hehe, good point, though smart hardware could still clamp it to the width of
the register.
Ioannis Vranos - 23 Nov 2004 23:56 GMT
>   The problem is that you're not programming
>   in assembler/machine code. If you're in
[quoted text clipped - 3 lines]
>   undefined. As for MC++ -- I don't know
>   that.

This is true concerning portability. However it has not anything to do
with system-specific code.

I think the main factor for the OP issue, is that the target machine is
not his x86 but the CLR when he uses managed code.

Signature

Ioannis Vranos

Hendrik Schober - 24 Nov 2004 10:45 GMT
> [...]
>
> This is true concerning portability. However it has not anything to do
> with system-specific code.

 True.
 However, nowadays, when you target std C++
 /and/ MC++, you're alreday coding to two
 different platforms. I think not very many
 developers here realize that they actually
 are porting their code between two platforms
 hwen they do that.

> [...]

 Schobi

Signature

SpamTrap@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett

Ioannis Vranos - 24 Nov 2004 11:14 GMT
>   True.
>   However, nowadays, when you target std C++
>   /and/ MC++, you're alreday coding to two
>   different platforms.

What do you mean. When you use /clr you are actually targeting CLR.

> I think not very many
>   developers here realize that they actually
>   are porting their code between two platforms
>   hwen they do that.

Well, let me provide another example. In .NET
(http://msdn.microsoft.com/netframework) long is System::Int32.

However this is not required for all CLI environments, so for example in
DotGNU (http://www.gnu.org/projects/dotgnu) or Mono
(http://www.mono-project.com) or some other CLI VM, it can be otherwise.

We can say that code assuming long being System::Int32 is .NET specific
and this assumption is not portable (causes undefined behaviour in a CLI
system having long as another type).

Signature

Ioannis Vranos

Hendrik Schober - 24 Nov 2004 11:53 GMT
> >   True.
> >   However, nowadays, when you target std C++
> >   /and/ MC++, you're alreday coding to two
> >   different platforms.
>
> What do you mean. When you use /clr you are actually targeting CLR.

 Yes. And when you don't use /clr, you are
 targetting x86. If you do both with the
 same code base, you have code that ports
 between two platforms.
 What I mean is, porting isn't as esotheric
 and rare as many think. Even what they now
 view as Windows-only (i.e., one platform)
 code often was ported from DOS to Win16 to
 Win32 and probably will get ported to .NET
 or Win64 or both. IME, porting is rather
 common and the attitude to do something
 based on the fact that some code runs only
 on one platform causes trouble later more
 often than people realize.

> [...]

 Schobi

Signature

SpamTrap@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett

Ioannis Vranos - 24 Nov 2004 12:43 GMT
>   Yes. And when you don't use /clr, you are
>   targetting x86. If you do both with the
[quoted text clipped - 10 lines]
>   on one platform causes trouble later more
>   often than people realize.

Yes I agree with you, we should try to be as much portable as possible.

I think I was not much comprehensible. :-) What I meant is that the
specific reason for OP problem was that his unportable/system-specific
code was not running against his x86 but against the CLR, and that's why
it did not execute as he expected.

In any case as you said, strictly ISO C++ speaking, his code was
unportable and invokes undefined behaviour.

Signature

Ioannis Vranos

Doug Harrison [MVP] - 22 Nov 2004 03:52 GMT
>> It's undefined to shift a value by an amount >= its length in bits, so you
>> need to avoid doing that.
[quoted text clipped - 3 lines]
>I wonder what can be the reason why the same code compiled for .net
>shouldn't give the same results as its native counterpart.

What I said comes from the C++ Standard, 5.8/1. (To be completely accurate,
s/value/promoted left operand/, but note that a 64-bit integer undergoes no
promotion in VC++.) The VC docs say the same thing:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_pl
uslang_shift_operators.asp

<q>
The results are undefined if the right operand of a shift expression is
negative or if the right operand is greater than or equal to the number of
bits in the (promoted) left operand.
</q>

I'm unable to find any information on the shift operators in MC++, but even
if the result were well-defined, I'd hesitate to take advantage of it.

Signature

Doug Harrison
Microsoft MVP - Visual C++

Peter Bromley - 23 Nov 2004 21:00 GMT
>>>It's undefined to shift a value by an amount >= its length in bits, so you
>>>need to avoid doing that.
[quoted text clipped - 17 lines]
> I'm unable to find any information on the shift operators in MC++, but even
> if the result were well-defined, I'd hesitate to take advantage of it.

So, that makes things very clear. I should have consulted MSDN before
posting.

It is interesting though that __int64 << and >> use function calls (I
presume into clr code). Perhaps a debug version of these functions which
throws ArgumentException would be useful. Just a thought.

Anyway, I have restructured my code so that 64 is never passed to the <<
 operator (which is what triggered my inquiry).

Thanks to all,

Peter

Signature

If you wish to reply to me directly, my addres is spam proofed as:

pbromley at adi dot co dot nz

Or if you prefer - nospam@nowhere.com  :-)

Ioannis Vranos - 22 Nov 2004 03:58 GMT
> This thru for mc++ only, right? Shifting in x86 is well defined, for
> unsigned 0s are shifted in, for signed the sign bit is extended when needed.
> I wonder what can be the reason why the same code compiled for .net
> shouldn't give the same results as its native counterpart.

I suppose this happens because in managed applications you do not
program against your x86 but the .NET VM which has its own assembly
language etc.

So your x86 system-specific code does not work the same to this
different "machine".

To see detailed technical info for .NET (CLI) specific code, you may
download the latest CLI standard:

http://www.ecma-international.org/publications/standards/Ecma-335.htm

which also contains the specification of its assembly language.

A book on this assembly language:

http://www.amazon.com/exec/obidos/tg/detail/-/0735615470/qid=1098782013/sr=1-1/r
ef=sr_1_1/103-4164487-6451810?v=glance&s=books


Signature

Ioannis Vranos


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.