shift, signed unsigned

O

Old Wolf

Schüle Daniel said:
Hello Newsgroup,

I was thinking about integer literals and what default types they get
and how they behave when applied to shift operator

Buy the C++ standard, it answers all of your questions :)
assume sizeof(int) == sizeof(unsigend int) = 4

int ii = -1024;
cout << (ii>>1) << endl; // -512
cout << (ii>>2) << endl; // -256
cout << (-4>>1) << endl; // -2
cout << (-4>>2) << endl; // -1
cout << (-4>>3) << endl; // -1

as one can see -1>>1 doesn't drop to 0
(I would expect it)
is this standard behaviuor?

Right-shifting a negative number is implementation-defined.
(Obviously what's happening is that 111........111 being
right-shifted is still 111.........111).
cout << (1<<31) << endl;
1 has type int, 1 << 31 would set the sign bit
if the expression remains "int" it would be negative
if on the other hand, it would be converted to
"unsigned int" it would be positive
I do get -2147483648 so my compiler chooses it to
remain "int". Again is this standard or impl. defined?

1 << 31 has the value of 2 to the power 31. This value
can't be represented by an int, so the behaviour is
undefined. (This is the same as any other integer overflow).
cout << (1U<<31) << endl;
1U has type "unsigned int", so is 1U<<31 too
I get here 2147483648
I think this is always ok.

2^31 can fit in an unsigned integer, so there's no problem here.
cout << typeid(0x8000000).name() << endl; // i *
cout << typeid(0x80000000).name() << endl; // j **

gcc (GCC) 4.0.2
i means int, j means unsigned int
I always thought that literals like 1 or 100
are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
but what I see here is that compiler puts ** in "unsigned int".

2.13.1#2 says:

If it is octal or hexadecimal and has no suffix, it has the
first of these types in which its value can be represented:
int, unsigned int, long int, unsigned long int.

0x8000000 (2^27) fits in an int, so it is an int.
0x80000000 (2^31) does not fit in an int but does fit in an
unsigned int, so it is an unsigned int.
(If it wouldn't do it, we would get negative number.)

2^31 is a large positive number. It is never negative. Many
people get this wrong. You might get a negative number as
the result of implementation-defined behaviour when you try
and assign this large positive number, to a signed int that
cannot hold such a large number.
 
V

Victor Bazarov

Schüle Daniel said:
I was thinking about integer literals and what default types they get
and how they behave when applied to shift operator

assume sizeof(int) == sizeof(unsigend int) = 4


int ii = -1024;
cout << (ii>>1) << endl; // -512
cout << (ii>>2) << endl; // -256

so the sign remains, meaning the most left bit is
not shifted, is this standard behaviour or impl. defined?
Implementation-defined.

cout << (-4>>1) << endl; // -2
cout << (-4>>2) << endl; // -1
cout << (-4>>3) << endl; // -1

as one can see -1>>1 doesn't drop to 0
(I would expect it)
is this standard behaviuor?
Implementation-defined.

cout << (1<<30) << endl;
1 has type int, 1 << 30 is int too, so this is ok
Yes.

cout << (1<<31) << endl;
1 has type int, 1 << 31 would set the sign bit
if the expression remains "int" it would be negative
if on the other hand, it would be converted to
"unsigned int" it would be positive
I do get -2147483648 so my compiler chooses it to
remain "int". Again is this standard or impl. defined?

Kind of. The result of (1<<31) is the same as

(1 * 2^31) % (UINT_MAX+1)

Since the destination type is signed, and the value can be
represented, it is represented using the same bit pattern,
otherwise it's implementation-defined.
cout << (1U<<31) << endl;
1U has type "unsigned int", so is 1U<<31 too
I get here 2147483648
I think this is always ok.
Yes.

and the last question

cout << typeid(0x8000000).name() << endl; // i *
cout << typeid(0x80000000).name() << endl; // j **

gcc (GCC) 4.0.2
i means int, j means unsigned int
I always thought that literals like 1 or 100
are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
but what I see here is that compiler puts ** in "unsigned int".

Yes. According to the Standard.
(If it wouldn't do it, we would get negative number.)
Why chooses compiler unsigned int? it this standard behaviour or impl.
defined?

Not really. The sequence it tries is 'int', then 'unsigned', then 'long',
then 'unsigned long'. If there is no suffix, that is.

V
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

Hello Newsgroup,

I was thinking about integer literals and what default types they get
and how they behave when applied to shift operator

assume sizeof(int) == sizeof(unsigend int) = 4


int ii = -1024;
cout << (ii>>1) << endl; // -512
cout << (ii>>2) << endl; // -256

so the sign remains, meaning the most left bit is
not shifted, is this standard behaviour or impl. defined?



cout << (-4>>1) << endl; // -2
cout << (-4>>2) << endl; // -1
cout << (-4>>3) << endl; // -1

as one can see -1>>1 doesn't drop to 0
(I would expect it)
is this standard behaviuor?



cout << (1<<30) << endl;
1 has type int, 1 << 30 is int too, so this is ok

cout << (1<<31) << endl;
1 has type int, 1 << 31 would set the sign bit
if the expression remains "int" it would be negative
if on the other hand, it would be converted to
"unsigned int" it would be positive
I do get -2147483648 so my compiler chooses it to
remain "int". Again is this standard or impl. defined?

cout << (1U<<31) << endl;
1U has type "unsigned int", so is 1U<<31 too
I get here 2147483648
I think this is always ok.


and the last question

cout << typeid(0x8000000).name() << endl; // i *
cout << typeid(0x80000000).name() << endl; // j **

gcc (GCC) 4.0.2
i means int, j means unsigned int
I always thought that literals like 1 or 100
are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
but what I see here is that compiler puts ** in "unsigned int".
(If it wouldn't do it, we would get negative number.)
Why chooses compiler unsigned int? it this standard behaviour or impl.
defined?

Regards, Daniel
 
D

dc

Here is a simple rule:

Right shift of unsigned number : inserts bit 0 from MSB/Left
Right shift of signed number : inserts bit 1 from MSB/Left

Left shift behaves same for both signed and unsigned number:
inserts bit 0 from LSB/Right
 
M

m_schellens

dc said:
Here is a simple rule:

Right shift of unsigned number : inserts bit 0 from MSB/Left
Right shift of signed number : inserts bit 1 from MSB/Left

Probably that rule is a bit too simple:
What about postive signed numbers and signed zero?

Cheers,
Marc
 
D

dc

Ok .. Read signed number as negative numbers
Unsigned number as positive numbers...


Thanks 4 catching...
 

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

Staff online

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top