Discussion 3 Richard Guo Advanced C 01/28/09 1. Answers to Last Time's Problems 1. #include <stdlib.h> int increment (int ptr); int ptr; // will not actually get used b/c masked by local variables with same name void main () // main doesn't have to return anything. valid. int *ptr = (int *) malloc (sizeof(int)); // valid. Will mask global variable // sizeof should be int* (logic error), but fine b/c int* = int = 4 bytes ptr = &ptr; // sets the ptr to point to itself. Not an error but still weird for (int a = 0; a < 1; a++) // creation of int here is invalid (syntax error) *(ptr--) = increment(&ptr); // (logic error) decrements ptr's value return; // return by itself without anything exits the funtion. valid int increment (int ptr); // (syntax error) cannot have a semicolon here return ptr++; // again, reusing variable name is bad form but still valid. 2. int width=0, i; scanf ("%d", &width); // you should check whether you got valid input matrix = (int *)malloc(width*width*sizeof(int)); printf ("%d ", matrix[i]); // doesn't factor in nice spacing if ((i+1) % width == 0) printf ("\n"); 3. int width=0, i, x, y, avg; scanf ("%d", &width); // you should check whether you got valid input matrix = (int *) malloc(width*width*sizeof(int));
if (i % width!= 0 && i % width!= width-1 && i > width && i < width*width-width) // not on edges avg = 0; for (x = -1; x < 1; x++) for (y = -1; y < 1; y++) avg += matrix[i+y*width+x]; avg /= 9; printf ("%d ", i); // doesn't factor in nice spacing if ((i+1) % (width) == width-1) // if on the end of the row printf ("\n"); // output a newline 4. #include <stdlib.h> int main(int argc, char** argv) int width=0, i; if (argc == 2) width = atoi(argv[1]); matrix = (int *)malloc(width*width*sizeof(int)); printf ("%d ", matrix[i]); // doesn't factor in nice spacing if ((i+1) % width == 0) printf ("\n"); 2. Array of Arrays Method 1 (simple to code but harder to access) int width, height; int *array; // fill in width, height via scanf, etc. array=malloc(width*height*sizeof(int)); array[width*x+y] // to access x, y free(array); // free up memory Method 2 (easier to access, but more complex code) int width, height; int **array; // fill in width, height via scanf, etc. array=malloc(width*sizeof(int*)); for (a = 0; a < width; a++) array[a]= malloc(height*sizeof(int)); array[x][y] // access position x, y for (a = 0; a < width; a++) free(array[a]); // free each column free(array); // free width
3. I/O Operations We've seen printf in the first discussion. You've used scanf in lab. Now we introduce to you sprintf. It follows the printf notation but stores the output sting in a variable instead of printing to the terminal. sprintf (char* destination_string, const char * format,...); char *temp; printf ( %d + %d = %d, x, y, x) // print to screen sprintf (*temp, %d + %d = %d, x, y, x) // puts the same string into temp There is also a command called fprintf that outputs to a local file. 5. Struct, Union, and Typedef Command Function Example typedef type1 type2 type2 var2; struct typename type1 member1; type2 member2; ; typename varname; union typename type1 member1; type2 member2; ; typename varname; enum enumname NAME1 = 1, NAME2 = 3; // setting equal to a number is optional. If not done, numbers are sequential Substitutes variable type type1 for type2 whenever type2 is seen in your code. Groups multiple variable types under one. Similar to classes in storing public variables but different in that struct doesn't allow methods. Structures use memory <= the combined sizes of its members. Similar to structure, but memory is shared and enough is allocated for the largest type. This means only one of its members can be used at a time. Allows renaming of numbers as something more legible. So, instead of testing whether a variable == 1, 2,... we can test whether it equals ERROR_SEG, ERROR_BUS,... string blurb = blah ; struct person ; // outside main person me; // inside main me.name = Richard ; me.age = 20; union numbers int a; float b; char c; ; // outside main numbers my_numbers; my_numbers.a = 1; my_numbers.b = 0.1234; // a is overwritten by b enum suits CLUBS, DIAMONDS, HEARTS, SPADES; enum suits hand; //in main hand = HEARTS; hand = 2; // same as above
The code on the left returns an error while the code on the right works. Why? struct person ; person * new_person = (person*)malloc(sizeof(person)); return 0 typedef struct person person_var; person_var * new_person = (person_var*)malloc(sizeof(person_var)); return 0; C is lazy/stupid. It does not recognize person as a new data type. The typedef statement defines person_var as a data type that can be used just like int, char, float, etc. 6. More Fun With Memory Uh-oh... Fragmentation Memory that is freed up in the middle of program execution causes fragmentation because memory is now noncontiguous. When malloc is called to find available memory, it can use various algorithms: Best First Next Scans all free chunks of memory. Returns the smallest contiguous section that is bigger than or equal to the requested amount of memory. Slow but guarantees most efficient use of memory. Scans from the beginning and returns the address of free memory first encountered that is >= to requested amount. Very fast but possibly inefficient. Same as first fit except that instead of starting at the beginning of memory space, remember where the last malloc finished and start from there. Simple way of being relatively balanced.
7. Solved Problems Bitwise operator problem write a program to simulate a 32 bit barrel shifter. That is, prompt for the number of bits to shift (positive = to the right, negative = to the left). Then rotate the number by that many bits. E.g. an 8 bit number 11010011 shifted to the right by 3 bits would give 01111010. unsigned int number=0, overflow_mask=0, overflow=0; int shift=0; scanf ("%d", &number); // you should check whether you got valid input printf ("\nhow much do you want to shift by? "); scanf ("%d", &shift); // you should check whether you got valid input if (shift < 0) // shift left shift *= -1; // make amount of shift positive overflow_mask = 0xFFFFFFFF << (32 shift); // generate mask overflow_mask = overflow_mask & number; // copy masked bits in number overflow_mask = overflow_mask >> (32 shift); // shift mask down number = number << shift; // rotate number else if (shift > 0) // shift right overflow_mask = 0xFFFFFFFF >> (32 shift); // generate mask overflow_mask = overflow_mask & number; // copy masked bits in number overflow_mask = overflow_mask << (32 shift); // shift mask up number = number >> shift; // rotate number number = number overflow; // paste masked bits back into zeros in number printf("%u\n", number); // output 8. More Problems (solutions will be on *next* discussion's handout) 1. Write a program to create a linked list a data type where each node stores a value and points to the next node in the list.