# Rest of Chapter 14

## Unions

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 example

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 ;
```

### Issues

• Size of the `union` structure
• Dangers of assigning the wrong field
• ICMP include

## Enumerated types

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} ;
```

## Functions as parameters

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) ;
}
```

### Function of functions or function returning a parameter

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 */
```

### Inconsistencies

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.

Consequently, the following two statements are legal and perform the same action when `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) ;
```

## A complex, though functional, example

```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 */
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) ;
}
```

## Complex declarations

1. overriding parentheses go first
2. postfix functional parentheses and array braces go next
3. prefix pointer asterisks go last

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)) ;`