odd binary bahavior

Started by
9 comments, last by Conner McCloud 18 years, 4 months ago
Just when you thought you knew it all - it decides to get all jewish on you...I'm trying to get the max range for a unsigned short but I'm having a bit of trouble. I know there's more than one way to do this ( SHRT_MAX, etc.. ) but I'm doing it this paticular way for learning purposes. My system is 32 bit and Im programming in C.

int main(int argc, char **argv)
{
	signed short signed_short = ~0; // int literals bits flipped to 1 then truncated & assigned to short.
	// visual bit pattern representation: 1111 1111  1111 1111

	// verify short is two bytes
	printf("sizeof(short) %d", sizeof(short)); // prints 2 - good

	signed_short &= 0x7fff; // mask out MSB
	// visual bit pattern representation: 0111 1111  1111 1111
	// print signed short max range:
	printf("signed short max range %d\n", signed_short); // should be: 32767 - prints: 32767 - good

	signed_short = ~0; // set all 16 bits to 1 again
	// visual bit pattern representation: 1111 1111  1111 1111

	// Now correct me if I'm wrong, in the following problem I will argue how I think mixing signed & unsigned
	// doesn't matter. Print max range for unsigned short with signed_short variable - ! mixing types !
	// continue reading...
	printf("unsigned short max range %u", signed_short); // should be: 65535 - what is printed: 4294967295
	// what is printed is the max range for an unsigned int. Now, I understand "%u" interprets signed_short
	// as an unsigned int (temporary conversion) the bit pattern for signed_short looks like
	// this: 1111 1111  1111 1111 after the "%u" conversion, it should look like 
	// this: 0000 0000  0000 0000  1111 1111  1111 1111 That's how I think it all works out and this last
	// printf call should have printed 65535 even though it's been interpreted as an int. Why? because the
	// left-most added WORD (as shown above) are all 0's and the right-most WORD are all 1's .. but it's as
	// if (or is) all the bits in the unsigned int interpretation are set to 1's:
	// 1111 1111  1111 1111  1111 1111  1111 1111 == 4294967295

	// declaring the variable as unsigned short solves the problem but I don't understand why declaring it signed
	// short should make a difference *here* since I'm not doing anything special on it like math where mixing
	// un/signed would probably make a difference. I'm only manually setting the bits and interpreting the variable
	// as an unsigned int in the last printf and it should behave as I described.

	getchar();
	return 0;
}



xeddiex
one..
Advertisement
Integral values passed to variadic functions undergo integer promotion. Even though you wanted to pass a signed short, printf() received an int. When passing an unsigned short it undergoes promotion to a unsigned int which preserves the value you want.
I believe the header file you are looking for is limits.h, and the pertinent macros are (U)SHORT_MAX and (U)SHORT_MIN.

*edit: Nevermind, you know about this [sad]

CM
Promotion is the word I should have used, I had it in the back of my mind but anyways. SiCrane, That's exactly what I'm trying to say; "When passing an unsigned short it undergoes promotion to a unsigned int which preserves the value you want." So therefore, the bit pattern for a short like 1111 1111 1111 1111 should look like this
after integral promotion 0000 0000 0000 0000 1111 1111 1111 1111. This however, hasn't answered my question [grin]
one..
Quote:Original post by Conner McCloud
I believe the header file you are looking for is limits.h, and the pertinent macros are (U)SHORT_MAX and (U)SHORT_MIN.

*edit: Nevermind, you know about this [sad]

CM


Yeah, I knew that Conner [grin] Thanks anyways.


xeddiex

one..
Because integral promotion for a signed short to a signed int preserves value. Preserving value for a signed short to a signed int involves sign extension. Similarly integral promotion for a unsigned short to an unsigned int preserves value, which involves zeroing out the upper half.
Quote:Original post by xeddiex
Promotion is the word I should have used, I had it in the back of my mind but anyways. SiCrane, That's exactly what I'm trying to say; "When passing an unsigned short it undergoes promotion to a unsigned int which preserves the value you want." So therefore, the bit pattern for a short like 1111 1111 1111 1111 should look like this
after intregal promotion 0000 0000 0000 0000 1111 1111 1111 1111. This however, hasn't answered my question [grin]

The sign of a signed value gets preserved under integral promotion...so all those zeros become ones.

CM
Think about what happens when you do:
short a = -3; //a = 0xFFFDint b = a;  //b = 0xFFFFFFFD
The compiler knows that if the number is negative, to make the upper 16-bits ones so that the number is the same.

And be careful what you say, as you could potentially appear racist here.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Quote:Original post by SiCrane
Because integral promotion for a signed short to a signed int preserves value. Preserving value for a signed short to a signed int involves sign extension. Similarly integral promotion for a unsigned short to an unsigned int preserves value, which involves zeroing out the upper half.


Ok, SiCrane. I hope I got this right.


You said promotion from said types preserves value and signdness:

signed short: 1111 1111 1111 1111

After promotion to signed int: 1000 0000 0000 0000 1111 1111 1111 1111

After reading, Conner's latest post; it's as I suspected; All the bits get set but I'm not quite understanding why *all* the bits in the "promoted to signed int" are being set to 1 if the value being preserved only takes up the first half of the WORD and it should look like in the above example. Hmm, so I guess it preserves more than the value and signedess? everything after the first half, regardless if the bits are set or not are set to 1?
one..
When (short)-1 gets promoted to int, the value of the int afterwards is the same, -1. The bit pattern for a 32 bit signed int that has the value -1 is 1111 1111 1111 1111 1111 1111 1111 1111. Sign extension takes the most significant bit of the short and fills the entire upper half of the bit pattern with that value. (short)-1 is 1111 1111 1111 1111, so it takes the 1 and fills the entire upper half of the int with 1. (short)7 is 0000 0000 0000 0111, so it takes the most significant bit, 0, and fills the entire upper half of the int to get (int)7, 0000 0000 0000 0000 0000 0000 0000 0111.

This topic is closed to new replies.

Advertisement