# ECE 209 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 there 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 Intergrate0to1(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) ;
}
```

### Resolving or accepting inconsistencies?

These are also valid ASNI C.

```double Intergrate0to1(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 ;
}
```
```double Intergrate0to1(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 ;
}
```

### The functional

```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 parenthesis and array braces go next
3. prefix pointer astericks go last

Try out these examples from the textbook

• `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 sections

• `int(*compar)(const void *, const void *) ;`
• `int (*IDChecker[5])(int ID) ;`
• `int(*T)(int(*f)(int ID)) ;`
• `int(*T)(int(*)(int)) ;`