# Tips

*Binary:*

The numbers we use on a day-to-day basis are decimal values, based on powers of ten. However, numbers can also be expressed in different ways, such as binary. A ** binary number** is a value expressed in powers of two instead of powers of ten.

To convert a decimal number to a binary number, we first take into consideration the powers of twos and their corresponding decimal values:

23= 8 |
22 = 4 |
21 = 2 |
20 = 1 |

These represent the values held in each column of a binary number. A one in a column indicates counting the number towards the sum, while a zero means to ignore it. Thus, one can be represented as 0001, two as 0010, four as 0100, and eight as 1000.

Other decimal values can be made up using a combination of ones and zeros:

*5 = 0101**6 = 0110**10 = 1010*

*Hexadecimal:*

Since binary data can be long and difficult to deal with, hexadecimal notation was developed to make representing binary easier. In ** hexadecimal notation**, four bits (a nibble, 8 bits is a byte) can be represented using a single digit. The values of 0 – 9 and A – F are used to represent the values 0 – 15.

Decimal |
Hexadecimal |
Binary |

0 | 0 | 0000 |

1 | 1 | 0001 |

2 | 2 | 0010 |

3 | 3 | 0011 |

4 | 4 | 0100 |

5 | 5 | 0101 |

6 | 6 | 0110 |

7 | 7 | 0111 |

8 | 8 | 1000 |

9 | 9 | 1001 |

10 | A | 1010 |

11 | B | 1011 |

12 | C | 1100 |

13 | D | 1101 |

14 | E | 1110 |

15 | F | 1111 |

*0xFFFFFFFF* is much easier to read and write than *1111 1111 1111 1111 1111 1111 1111 1111*

*Signed & Unsigned:*

The difference between a signed and an unsigned integer is that a ** signed integer can represent either a positive or negative number** while

*an unsigned integer can only represent positive number.*As we know, in the case of an *unsigned (no negatives) integer*, the binary value *1111* is representative of the decimal value *15*.

However, in a *signed (positives and negatives) integer*, the leftmost bit will now represent a negative value:

23= -8 |
22 = 4 |
21 = 2 |
20 = 1 |

So the binary value *1111* will equal the decimal value *-1*. Therefore, the maximum positive value that a signed integer can represent is a zero followed by all ones, in this case *0111 = 7*.

A standard integer in C will be signed. Unsigned integers have to be explicitly declared: *unsigned int b;*

*Other Bitwise Operators:*

Aside from left shifts and right shifts, there are a few other important bitwise operators to consider. These are and (&), or ( | ), not (~) and exclusive-or/xor (^).

This picture helps to summarize how each of these operators functions:

The “and” operator (&) returns a 1 only in columns where there are two 1s. All other combinations return a 0.

- 10101010
- & 11001100
- 10001000

The “or” operator ( | ) returns a 1 in columns where there is at least one 1. Only the combination of two 0s returns a 0.

- 10101010
- | 11001100
- 11101110

The “not” operator (~) simply reverses all bits, meaning that 1s will become 0s and vice-versa.

- ~ 10101010
- 01010101

The “xor” operator (^) returns a 1 in columns where there is only 1. Columns with two 0s or two 1s will return a 0.

- 10101010
- ^ 11001100
- 01100110

*Pointers:*

** Pointers** are variables that store or “point to” an

**, where in memory some object or variable is stored.**

*address*Pointers are declared in C in the format *type* typePtr; *where *type* is the datatype of the variable (int, char, float, etc.) and *typePtr* is the name.

The following example initializes variable *int i* to *10* and stores the address of this variable in *iPtr*:

** Dereferencing** means to follow the pointer to the object or obtaining the value stored in a pointer’s address. This process also utilizes an asterisk.

What would the example above print? *The address of the variable i and then the value stored there (10).*

The exercise we went over in class had us write a program with two variables (*int i* and *int* iPtr*) that would return the values from 0 to 9 using a for loop without referring to *int i* except for initializing the value of *iPtr*. Code for that exercise:

Common assembly instructions are listed in the image below (click to view as larger):

When converting from a decimal to a binary floating point value, there are three main parts that are necessary to take into consideration–the sign, the exponent value, and the mantissa.

In 32-bit systesms, the sign contains 1 bit, the exponent contains 7, and the mantissa contains the remaining 24.

In 64-bit systems, the sign contains 1 bit, the exponent contains 11, and the mantissa contains the remaining 52 bits.

Let’s say the value we are converting from decimal to binary is 2.5. We will use a 32-bit system for this example.

To start, we **first** must write out 2 as binary. This is 0010. Next, we must write out .5 as binary. If we imagine there is a decimal point after 2 written in binary, then the next value after the decimal point is equivalent to 1/2, then 1/4, 1/8, 1/16, 1/32, and so on.

Therefore, .5 would just correspond with a 1 directly after the decimal point followed by all zeros: .100…

Putting the binary representation for 2 and .5 together, we get 0010.10 as the starting value.

**Next**, we move the decimal point to the right or left until we get a single 1 in front of the point. In this case, we move the decimal point once to the left, resulting in 1.010 x 2^1. The exponent 1 is positive since we must move the decimal point once to the right to obtain the original value.

**Now**, we store anything after the decimal point in 1.010 x 2^1 in the mantissa field, resulting in 010. **Also**, since we know that the number is positive, we can place a 0 in the sign field (1 if number were negative).

**Then**, to get the exponent value, we take the exponent in the following value and add the bias to it: 1.010 x 2^* 1*.

In a 32-bit system, the bias is 0111111. In a 64-bit system, the bias is 01111111111. In all cases, the bias will be a zero followed by all ones.

*Adding exponent and bias:*

0000001

+ 0111111

1000000

**Therefore**, the final value is 1000000. This is the value stored in the exponent field.

Our final result is:

Here is a good website to use to verify your conversions from a base-10 to base-2 floating point!

* 1*. The first program converts from decimal to hexidecimal using arithmetic and bitwise operators.

* 2*. There are a few points to take away from this second program.

**, what #define means in the line #define N (32) is that N is set to the permanent value of 32. Anywhere N shows up in the rest of the program will have the value 32.**

*Firstly*** Next**,

*int comp(const void* p1, const void* p2) {*

* return *((int*) p2) – *((int*) p1);*

*}*

This function converts void* p1 and void* p2 into int* by casting using (int*) p2 and (int*) p1. Taking these two and placing an asterisk in front dereferences the pointer, meaning that p1 and p2 are followed to the address they point to and the value stored there is obtained. Overall, all this function is doing is subtracting the value in p1 from the value in p2.

** Then**, it is important to know what this line does:

int* array = malloc(N * sizeof(int));malloc is a function that allocates a given amount of memory space on the heap. In this case, it would be N integers. Since we have the line #define N (32), we know that N is 32. So, in this malloc line, there is enough space for 32 integers allocated on the heap. Always remember that when you use malloc, you must use the free function at the end: free(array);, I wanted to remind everyone that an array pointer will always point to the starting address of an array. Therefore, in this lineFinally

while (p >= array)the block executes just as long as p (defined as an int pointer) is greater than the starting address of the array.3. The assembly is already annotated line by line in the file. Common assembly instructions are given in Week 04 below.4. These two programs deal with a file that is shared between the producer and the consumer. The producer can create the file if it doesn't exist and read the file as well as write into it, as seen in this line:

int outfile = open(sharedFile, /* name */*/ Meanwhile, the consumer can only read it.O_CREAT|O_RDWR, /* create, read/write */ S_IRUSR | S_IWUSR | S_IXUSR | /* owner's rights */ S_IROTH | S_IWOTH | S_IXOTH); /* others' rights

int infile = open(sharedFile,O_RDONLY);

*Sizes of Data Types:*

*Formatting:*

# Videos and Handouts