Enabling or Disabling the Sign Bit

Submitted by tushar pramanick on Thu, 03/07/2013 - 13:05

Enabling or Disabling the Sign Bit

As you know, it's very easy to express a negative number in decimal. All you need to do is put a minus sign in front of the absolute value of the number. But how does the computer represent a negative number in the binary format?

Normally, one bit can be used to indicate whether the value of a number represented in the binary format is negative. This bit is called the sign bit. The following two sections introduce two data modifiers, signed and unsigned, that can be used to enable or disable the sign bit.
The signed Modifier

For integers, the leftmost bit can be used as the sign bit. For instance, if the int data type is 16 bits long and the rightmost bit is counted as bit 0, you can use bit 15 as a sign bit. When the sign bit is set to 1, the C compiler knows that the value represented by the data variable is negative.

There are several ways to represent a negative value of the float or double data types. The implementations of the float and double data types are beyond the scope of this book. You can refer to Kernighan and Ritchie's book The C Programming Language for more details on the implementations of negative values of the float or double type.

The C language provides a data modifier, signed, that can be used to indicate to the compiler that the int or char data type uses the sign bit. By default, the int data type is a signed quantity. But the ANSI standard does not require the char data type be signed; it's up to the compiler vendors. Therefore, if you want to use a signed character variable, and make sure the compiler knows it, you can declare the character variable like this:

signed char ch;

so that the compiler knows that the character variable ch is signed, which means the variable can take a value in the range of -128 (that is, -27) to 127 (that is, 27_1).

(Remember that for an unsigned character variable, the range is 0 to 255; that is, 28_1.)

TIP

    To represent a negative number in the binary format, you can first get its equivalent positive value's binary format. Then you perform the complement operation on the binary, and finally, add one to the complemented binary.
    For instance, given a negative integer -12345, how can you represent it in the binary format?
    First, you need to find the binary format for the positive integer 12345, which is 0011000000111001.
    Then, you perform the complement operation on 0011000000111001; that is, ~0011000000111001, and obtain the following:

    1100111111000110

    And finally, adding 1 to 1100111111000110 gives you 1100111111000111, which is the binary format of the negative integer -12345.

The unsigned Modifier

The C language also gives you the unsigned modifier, which can be used to tell the C compiler that no sign bit is needed in the specified data type.

Like the signed modifier, the unsigned modifier is meaningful only to the int and char data types.

For instance, the declaration

unsigned int x;

tells the C compiler that the integer variable x can only assume positive values from 0 to 65535 (that is, 216_1), if the int data type is 16 bits long.

In fact, unsigned int is equivalent to unsigned according to the ANSI standard. In other words, unsigned int x; is the same as unsigned x;.

Also, the ANSI standard allows you to indicate that a constant is of type unsigned by suffixing u or U to the constant. For instance,

unsigned int x, y;
x = 12345U;
y = 0xABCDu;

Here, the unsigned integer constants 12345U and 0xABCDu are assigned to variables x and y, respectively.

The program in Listing 9.1 is an example of using the signed and unsigned modifiers.

TYPE
Listing 9.1. Modifying data with signed and unsigned.


1:  /* 09L01.c: Using signed and unsigned modifiers */
2:  #include <stdio.h>
3:
4:  main()
5:  {
6:     signed char  ch;
7:     int          x;
8:     unsigned int y;
9:
10:    ch = 0xFF;
11:    x = 0xFFFF;
12:    y = 0xFFFFu;
13:    printf("The decimal of signed 0xFF is %d.\n", ch);
14:    printf("The decimal of signed 0xFFFF is %d.\n", x);
15:    printf("The decimal of unsigned 0xFFFFu is %u.\n", y);
16:    printf("The hex of decimal 12345 is 0x%X.\n", 12345);
17:    printf("The hex of decimal -12345 is 0x%X.\n", -12345);
18:    return 0;
19: }


On my machine, the executable file of the program in Listing 9.1 is named 09L01.exe. (Note that when you compile the program in Listing 9.1, you'll see a warning message regarding the assignment statement ch = 0xFF; in line 10, due to the fact that ch is declared as a signed char variable. You can ignore the warning message.)

The following is the output printed on the screen after I run the executable from a DOS prompt:

C:\app> 09L01
The decimal of signed 0xFF is -1
The decimal of signed 0xFFFF is -1.
The decimal of unsigned 0xFFFFu is 65535.
The hex of decimal 12345 is 0x3039.
The hex of decimal -12345 is 0xCFC7.
C:\app>

OUTPUT
    As you see in Listing 9.1, line 6 declares a signed char variable, ch. The int variable x and the unsigned int variable y are declared in lines 7 and 8, respectively. The three variables, ch, x, and y, are initialized in lines 10_12. Note that in line 12, u is suffixed to 0xFFFF to indicate that the constant is an unsigned integer.

ANALYSIS
    The statement in line 13 displays the decimal value of the signed char variable ch. The output on the screen shows that the corresponding decimal value of 0xFF is -1 for the signed char variable ch.

Lines 14 and 15 print out the decimal values of the int variable x (which is signed by default) and the unsigned int variable y, respectively. Note that for the variable y, the unsigned integer format specifier %u is used in the printf() function in line 15. (Actually, you might recall that %u was used to specify the unsigned int data type as the display format in the previous hour.)

Based on the output, you see that 0xFFFF is equal to -1 for the signed int data type, and 65535 for the unsigned int data type. Here, the integer data type is 16 bits long.

Lines 16 and 17 print out 0x3039 and 0xCFC7, which are the hex formats of the decimal values of 12345 and -12345, respectively. According to the method mentioned in the last section, 0xCFC7 is obtained by adding 1 to the complemented value of 0x3039.

 

 

 

Related Items

Exercises : Answer the following Question

To help solidify your understanding of this hour's lesson, you are encouraged to answer the quiz questions and finish the exercises provided in the Workshop before you move to the next lesson.

Measuring Data Sizes

Measuring Data Sizes

What Does x?y:z Mean?

What Does x?y:z Mean?

In C, ?: is called the conditional operator, which is the only operator that takes three operands. The general form of the conditional operator is

Using Shift Operators

Using Shift Operators

There are two shift operators in C. The >> operator shifts the bits of an operand to the right; the << operator shifts the bits to the left.

The general forms of the two shift operators are

x >> y

Manipulating Bits

Manipulating Bits

In previous hours, you learned that computer data and files are made of bits (or bytes). There is even an operator in C_the sizeof operator_that can be used to measure the number of bytes for data types.