Thank you for the explanation, it makes more sense. The thing I was confused on was, what do I exactly shift? Do I shift ivar(user input/from code), or something else? I tried to shift like this;
sign = ivar >> 31(The number is 32 bits?)
and tried to print sign on to the screen, but all I get is a 0 even if I put in a negative number.
In short your doing it the right way.
For example:
unsigned char c1=63; //0x3f, binary: 0011 1111
unsigned char result=c1>>1; // 0x1f, binary: 0001 1111
if the value stored in your 'ivar' variable *is* 32bits then shifting it 31 should work. However some discussion is required on how numbers are stored in binary and variables.
The main issue is that while a char (for example) should be eight bits (in the above example, unsigned being eight data-bits, signed being 7 and a sign bit). This is not definite, depending on the operating system, compile options, compiler and a few other things the actual number of bits in a variable can vary.
Also there are two types of binary number, Big and Little endian. This basically refers to the order of the bits themselves (if the largest value is on the left or right respectively).
In short apart from knowing that an int *can* contain a certain value (between it's minimum and maximum) you have no real knowledge of how the number is stored on the bit level. it may be stored with the sign on the left, or right, the largest value bit may be on the left, or right and it may only be 32-bits, or 64, or 128....
As you can see this puts you, as a programmer for this task in a ####### of a position. Your only option is to make a function to find the ordering, size, and position of your data and sign.
You felling intimidated yet? I am!
First read this http://www.codeguru.com/Cpp/Cpp/algorithms/math/article.php/c10243/
I'm not going to go and do all the work for you but I will lay out the theory.
Firstly we need to know the ordering of the data, big or little endian, sign left or right. To accomplish this we can do something pretty simple.
signed Type Variable = 1 //where type is your variable type, int, char, etc
This basically states we want to assign 1 to the variable so lets take a look at the theory.
with the exemplar five bit byte:
1 could be
x 0 0 0 1 (endian to the right, sign right)
0 0 0 1 x (endian to the right, sign left)
x 1 0 0 0 (endian to the left, sign right)
1 0 0 0 x (endian to the left, sign left)
I'm using an 'x' above to indicate the sign location, it would be 0.
we can find out the endian by shifting our value again by one bit in a direction and comparing it. So if we
Variable=Variable<<1
if the endian is right the number will be two:
0 0 0 1 << 1 = 0 0 1 0 = 2
if the endian is left the number will be zero:
1 0 0 0 << 1 = 0 0 0 0 = 0
So in short if Variable != 0 we are indeed dealing with a right endian, else it's left (a simple bool value could be returned from the function to indicate this)
Now we need to know where the sign is, to do this we can again use shifting. however it will vary between each case (big or little endian).
For right endian we can assign a value of -1 (-1<<0).
the result will either be:
1 0 0 0 1 (sign right, then data)
0 0 0 1 1 (data, then sign left)
If we shift this right by one we know the results we will get.
1 0 0 0 1 << 1 = 0 0 0 1 0 = +2
0 0 0 1 1 << 1 = 0 0 1 1 0 = +3
In short, if the value of a right endian number is > 2, the sign is left, else it is right.
The same can be applied to a left endian value, however we must simply shift left and apply the oppose
1 1 0 0 0 (right sign)>> 1 = 0 1 1 0 0 = +3
0 1 0 0 1 (left sign) >> 1 = 0 1 0 0 0 = +2
so in this case if the number is left signed then the value <3.
So basically:
//Left endian:
if(value << 1 == <3) LeftSign=true;
else LeftSign=false;
//right endian
if(value << 1 == >2) LeftSign=true;
else LeftSign=false;
Once you know the order of the bits you now need to know the size. you'll have to accomplish this though a loop.
if the number is left endian then we will start with the number 1, then shift left untill the value is zero (we have shifted past the total number of bits)
the code would look something like this.
signed type Variable = 1;
Int Count =0;
while ( Variable != 0)
{
Count++;
Variable = Variable >> 1;
}
for our four-data bits (ignoring the fith sign)
1 0 0 0 (1) (count = 0)
0 1 0 0 (2) (count = 1)
0 0 1 0 (4) (count = 2)
0 0 0 1 (8) (count = 3)
0 0 0 0 (0) (count = 4)
So we now know that we have four data bits, and obviously we add 1 for the sign bit.
with a right endian the process is identical except you shift right (<<).
So having now found the size, order, and sign location we can shift correctly.
//For left endian, left signed with 5 bits total.
SignValue = Variable << 4; //shifts sign to one bit
//For left endian, right signed with 5 bits total.
StoreValue = Variable >> 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable << 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1)
//for right endian left signed
SignValue = Variable >> 4; // shifts sign to one bit
//for right endian right signed
StoreValue = Variable << 4; //shifts out everything except the sign value (places sign at highest possible number)
SignValue = Variable >> 3; //shifts sign back to the one bit (not needed but acceptable practice (this way you can use SignValue== 1)
Hopefully you followed me on all that, If you *know* for certain the code is going to be used on a specific windows system with a specific compiler you can skip all of that and go research the variable type's specifics for that system/compiler. However I'd deem it good practice and a good example to throw together a full set of functions for the job (put the prototypes in a header and the functions in a cpp including it). That way you will
A. Look really awesome
B. Look really clever
C. Have a nice library for bit shifting if you need it later.
D. Have lots of members of the opposite sex want to go out with you.
D != true