f



Left shift

Hi,
    how is this code working? As per me since aNum is int8 so left
shifting aNum by 8 would make it zero, how is it maintaining this? if
i left shift it by 32 it becomes zero?

   unsigned __int8  aNum = 5;
   printf("%d",aNum << 16);


Thanks
Keshav

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Keshav
10/30/2008 2:18:10 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

11 Replies
506 Views

Similar Articles

[PageSpeed] 11

Keshav wrote:
> Hi,
>    how is this code working? As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this?
> if i left shift it by 32 it becomes zero?
>
>   unsigned __int8  aNum = 5;
>   printf("%d",aNum << 16);
>
>

The code isn't working.  :-)

If you shift by more than the size of the integer, the result is
undefined.

On some hardware it might become zero, or stay unchanged, on still
others the shift count will be modulo the size, on others we don't
know.


Bo Persson


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Bo
10/30/2008 4:42:54 PM
On Oct 30, 1:18 pm, Keshav <gupta.kes...@gmail.com> wrote:
> Hi,
>     how is this code working? As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this? if
> i left shift it by 32 it becomes zero?
>
>    unsigned __int8  aNum = 5;
>    printf("%d",aNum << 16);

Just a guess: integral promotion? 16 is an int literal. An builtin
operator on a __int8 and an int will first promote the __int8 value to
an int, perform the int operation, and return the int value. Your
system appears to be a 32 bit system, and it appears int is the
natural word size of the machine, 32 bits, which explains why when you
shift it by 32 it becomes 0.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
JoshuaMaurice
10/30/2008 4:43:32 PM
On Oct 30, 3:18 pm, Keshav <gupta.kes...@gmail.com> wrote:
> Hi,
>     how is this code working? As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this? if
> i left shift it by 32 it becomes zero?

It would be useful if you can specify what was the actual output and
what was your expected output.  Also providing a complete compilable
code would be appreciated.  Here is an example, and everything works
as expected.

$ cat int8.cc
# include <iostream>
# include <bitset>
int main() {
   unsigned char i = 5;
   std::bitset<8> bi(i);
   for (int sp=0; sp < 10; ++sp) {
       unsigned char j = (i << sp);
       std::bitset<8> bj(j);
       std::cout << "i << " << sp << ": "
           << bj << std::endl;
   }
}

$ g++ int8.cc
$ ./a.exe
i << 0: 00000101
i << 1: 00001010
i << 2: 00010100
i << 3: 00101000
i << 4: 01010000
i << 5: 10100000
i << 6: 01000000
i << 7: 10000000
i << 8: 00000000
i << 9: 00000000
$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

$

Rgds,
anna

-- 
Love of a Father
http://missingrainbow.blogspot.com/2008/07/love-of-father.html


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
annamalai
10/30/2008 4:48:10 PM
On 30 Okt., 21:18, Keshav <gupta.kes...@gmail.com> wrote:
> Hi,
>     how is this code working?
Well - obviously it is not.
> As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this?

What makes you believe so? aNum << 16 is an integer expression, as
both opearands are converted to int. Also, shifting is undefined on an
integer number, so only shift unsigned quantities.
> if
> i left shift it by 32 it becomes zero?
Not necessarily. If your int is 32 bits, shifting by 32 (or larger)
gets implementation defined. I believe my compiler would return the
original number.
Only use shifts in lowlevel code, and only with unsigned values.
>
>    unsigned __int8  aNum = 5;
>    printf("%d",aNum << 16);
>
Also avoid printf, prefering std::cout. Especially in cases like this
where you seem to be unsure about the result of the parameters.
std::cout is cleaner and typesafe. printf might (sadly) have a
performance advantage with most common implementations, but unless it
really matters, stay away from the printf family.

/Peter


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
peter
10/31/2008 12:25:43 AM
Keshav wrote:
> Hi,
>     how is this code working? As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this? if
> i left shift it by 32 it becomes zero?
>
>    unsigned __int8  aNum = 5;
>    printf("%d",aNum << 16);

5.8/1: "The behavior is undefined if the right operand is negative, or
greater than or equal to the length in bits of the promoted left operand."

The question now is how long in bits the promoted aNum is. On 32-bit
systems where int is 32 bits long, aNum will be promoted to int,
aNum << 16 may not make it zero, and aNum << 32 will be undefined.

Note here that the shift operation is done not on a 8-bit value, but
on a 32-bit value. On the other hand, in this example:

     unsigned __int8 aNum = 5;
     aNum <<= 5;

the result will be assigned back to a 8-bit value, during which "the
laws of arithmetic modulo 2^n" applies and only the least significant
8 bits are taken, which is zero.

--
Seungbeom Kim

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Seungbeom
11/1/2008 8:47:31 AM
On Thu, 30 Oct 2008 14:18:10 CST, Keshav <gupta.keshav@gmail.com>
wrote in comp.lang.c++.moderated:

> Hi,
>     how is this code working? As per me since aNum is int8 so left
> shifting aNum by 8 would make it zero, how is it maintaining this? if
> i left shift it by 32 it becomes zero?
>
>    unsigned __int8  aNum = 5;
>    printf("%d",aNum << 16);

I see three replies already, but none of the correct.

Regardless of what you think "as per you", as per the C++ language
standard you are just plain wrong.

You are not shifting an 8-bit object, in fact you can't shift an 8-bit
value in C++.  When you perform an arithmetic or logical operation on
an integer type smaller than int, the value is promoted to either int
(in this case) or unsigned int (in some special cases).  This has
nothing to do with the type of the right hand operand.

So you are shifting a 16-bit or more likely a 32-bit integer rvalue
right by 16.  If int is 16 bits on your system, the behavior is
undefined.  It is undefined behavior to shift an integer type by a
negative value, or by a value greater than or equal to the number of
bits in the integer type.

There is no guarantee that any size shift will generate the value 0,
especially when shifting a signed type.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Jack
11/1/2008 8:48:28 AM
On Oct 31, 7:42 am, "Bo Persson" <b...@gmb.dk> wrote:
> Keshav wrote:
> > Hi,
> >    how is this code working? As per me since aNum is int8 so left
> > shifting aNum by 8 would make it zero, how is it maintaining this?
> > if i left shift it by 32 it becomes zero?
>
> >   unsigned __int8  aNum = 5;
> >   printf("%d",aNum << 16);
>
> The code isn't working.  :-)
>
> If you shift by more than the size of the integer, the result is
> undefined.
>
> On some hardware it might become zero, or stay unchanged, on still
> others the shift count will be modulo the size, on others we don't
> know.
>
> Bo Persson
>

Basically this is what happens, assuming a 32-bit machine:

unsigned __int8  aNum = 5;
printf("%d",(unsigned _int32)aNum << 16);

That is, there's promotion to a 32-bit data type so that things now
look like {0, byte-value, 0, 0}, a 32-bit value. The max you can shift
is 24.




--
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
mpho
11/1/2008 8:58:11 AM
> Also, shifting is undefined on an
> integer number,
the current ISO C++0x draft says, >> is implementation-defined for
negative integers, and for all positive integers, signed or unsigned,
equivalent to: x / (2 raised to y). So (aNum = 5) >> 32 is (or will be
in future) 0, regardless of what integer type aNum is.
I don't have the ISO 2003 version at hand.

Wolf Lammen

--
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
wolf
11/1/2008 9:57:12 AM
On Nov 1, 7:48 am, Jack Klein <jackkl...@spamcop.net> wrote:
> On Thu, 30 Oct 2008 14:18:10 CST, Keshav <gupta.kes...@gmail.com>
> wrote in comp.lang.c++.moderated:
>
> > Hi,
> >     how is this code working? As per me since aNum is int8 so left
> > shifting aNum by 8 would make it zero, how is it maintaining this? if
> > i left shift it by 32 it becomes zero?
>
> >    unsigned __int8  aNum = 5;
> >    printf("%d",aNum << 16);
>
> I see three replies already, but none of the correct.

The first reply, mine:

On Oct 30, 3:43 pm, JoshuaMaur...@gmail.com wrote:
> Just a guess: integral promotion? 16 is an int literal. An builtin
> operator on a __int8 and an int will first promote the __int8 value to
> an int, perform the int operation, and return the int value. Your
> system appears to be a 32 bit system, and it appears int is the
> natural word size of the machine, 32 bits, which explains why when you
> shift it by 32 it becomes 0.

Quoting the C++ 03 standard, 5.8 shift operators, subsection 3:
> The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has
> an unsigned type or if E1 has a signed type and a nonnegative value,
> the value of the result is the integral part of the quotient of E1
> divided by the quantity 2 raised to the power E2. If E1 has a signed
> type and a negative value, the resulting value is
> implementation-defined.

I'm curious, where was I wrong?

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
JoshuaMaurice
11/1/2008 8:43:24 PM
On 1 Nov., 16:57, "wolf.lammen" <wolf.lam...@googlemail.com> wrote:
> > Also, shifting is undefined on an
> > integer number,
>
> the current ISO C++0x draft says, >> is implementation-defined for
> negative integers, and for all positive integers, signed or unsigned,
> equivalent to: x / (2 raised to y). So (aNum = 5) >> 32 is (or will be
> in future) 0, regardless of what integer type aNum is.
> I don't have the ISO 2003 version at hand.
>
That is true: my wording was misleading. What I meant was that
shifting of signed integers is unspecified. You are correct that for
signed integers that turn out to be positive (as in the OPs code), the
result is well defined, but the point I tried to make (not to well!)
was that you should not shift signed integers: if they are less than
zero, you get unspecified behaviour and if they are bigger than zero,
you could just as well have used an unsigned quantity in the first
place.

As for the ability to shift with an arbitrary amount, you are mistaken
- at least according to my draft (n2798).

[expr.shift]
.... The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the promoted left
operand.

Thus, your shifting 32 bits will be undefined on a 32-bit machine -
also in C++0x.

/Peter

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
peter
11/2/2008 3:56:22 AM
JoshuaMaurice@gmail.com wrote:
> The first reply, mine:
> 
> On Oct 30, 3:43 pm, JoshuaMaur...@gmail.com wrote:
>> Just a guess: integral promotion? 16 is an int literal. An builtin
>> operator on a __int8 and an int will first promote the __int8 value to
>> an int, perform the int operation, and return the int value. Your
>> system appears to be a 32 bit system, and it appears int is the
>> natural word size of the machine, 32 bits, which explains why when you
>> shift it by 32 it becomes 0.
> 
> Quoting the C++ 03 standard, 5.8 shift operators, subsection 3:
[...]
> 
> I'm curious, where was I wrong?

You read 5.8/3, but missed 5.8/1.
See the previous post of mine in this thread.

-- 
Seungbeom Kim

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Seungbeom
11/2/2008 8:24:26 AM
Reply: