The union
is a structure in which only
one field can be active. The syntax for accessing union
fields is identical to the syntax for accessing structure fields.
Unions are confusing.
Color can be represented in many ways.
union Color { float hsb[3] ; int rgb[3] ; } union Color Red, Blue ; Red.rgb[0] = 255 ; Red.rgb[1] = 0 ; Red.rgb[2] = 0 ; Blue.hsb[0] = 0.6666666 ; Blue.hsb[1] = 1.0 ; Blue.hsb[2] = 1.0 ;
But how can you tell RGB from HSB?
struct Color { int type ; /* 0 for HSB, 1 for RGB */ union uc { float hsb[3] ; int rgb[3] ; } } struct Color Red ; Red.type = 1 ; Red.uc.hsb[0] = 255 ; Red.uc.hsb[1] = 0 ; Red.uc.hsb[2] = 0 ;
union
structure
Enumerated types are a great way to assign logical numbers
to useful integers.
They look better those DEFINE
's in the
ICMP include file.
/* p. 575 of textbook */ enum spectrum {red, orange, yellow, green, blue, violet} ; enum spectrum color ;
enum ececourses {ece109 = 109, ece209 = 209} ;
In C, functions can be passed function pointers, but not functions.
/* Function to perform a numeric integration */ double Integrate0to1(double(*f)(double), int N) { double sum = 0.0 ; int i ; sum = f(0.0)*0.5 ; for(i=1; i < N-1; ++i) sum += f(1.0/N) ; sum += f(1.0)*0.5 ; return sum/N ; }
/* Prototype for the standard C quicksort routine */ void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); struct course { char Dept[4] ; int Number ; } int CompareCourses(const void *V1, const void *V2) { struct course *C1 = (struct course *)V1 ; struct course *C2 = (struct course *)V2 ; int R = strncmp(C1->Dept, C2->Dept, 4) ; if (R) return R ; else return C1->Number - C2->Number ; } void SortCourseArray(struct course ManyCourses[1000]) { qsort((void *)ManyCourses, 1000, sizeof(struct course), CompareCourses) ; }
The following two function prototypes are very different.
int *pointy(int) ; /* a function returning a pointer to an integer */ int (*funky)(int) ; /* a pointer to a function returning an integer */
Unfortunately there are two conflicting styles for refering
to functions passed as parameters.
In one the *
is used and in the other it isn't.
f
is a parameter refering to function that
maps a double
into a double
.
sum = (*f)(0.0)*0.5 ; sum = f(0.0)*0.5 ;
Similarly, there is two different ways of passing functions to a functions. Either of the following will work.
Integrate0to1(sqrt, 1000) ; Integrate0to1(&sqrt, 1000) ;
int Always(int ID) { return 1 ; } int Perhaps(int ID) { return ID%7 == 3 ; } int Never(int ID) { return 0 ; } /* Array of ID checkers */ int (*IDChecker[5])(int ID) = { Always, Always, Perhaps, Never, Always } ; /* Function to see if ID checker accepts 0 as ID */ int TestIf0Accepted(int(*f)(int ID)) { return (*f)(0)==1 ; } /* Function to test if function to test ID checker really does */ int TooDurnComplicated(int(*T)(int(*f)(int ID))) { return (*T)(Always) ; } /* You really don't need that f or ID in the parameter list */ int TooHardToRead(int(*T)(int(*)(int))) { return (*T)(Always) ; } /* Function to test if function to test * if function to test ID checker really does */ int WasntTheLastOneEnough(int T(int(*)(int(*)(int)))) { return (*T)(TestIf0Accepted) ; }
Try out these examples from the textbook (p. 581).
int board[8][8] ;
int ** ptr ;
int * risks[10] ;
int (* rusks)[10] ;
int * off[3][4] ;
int (* uuf)[3][4] ;
int (* uof[3])[4] ;
Try out some examples from the functional section
int(*compar)(const void *, const void *) ;
int (*IDChecker[5])(int ID) ;
int(*T)(int(*f)(int ID)) ;
int(*T)(int(*)(int)) ;