   Home Books by K. N. King Short courses Recommended books Recommended links FAQ ### Chapter 14

#### Answers to Selected Exercises

2. [was #2] `#define NELEMS(a) ((int) (sizeof(a) / sizeof(a)))`

4. [was #4]

(a) One problem stems from the lack of parentheses around the replacement list. For example, the statement

```a = 1/AVG(b, c);
```

will be replaced by

```a = 1/(b+c)/2;
```

Even if we add the missing parentheses, though, the macro still has problems, because it needs parentheses around `x` and `y` in the replacement list. The preprocessor will turn the statement

```a = AVG(b<c, c>d);
```

into

```a = ((b<c+c>d)/2);
```

which is equivalent to

```a = ((b<(c+c)>d)/2);
```

Here's the final (corrected) version of the macro:

```#define AVG(x,y) (((x)+(y))/2)
```

(b) The problem is the lack of parentheses around the replacement list. For example,

```a = 1/AREA(b, c);
```

becomes

```a = 1/(b)*(c);
```

Here's the corrected macro:

```#define AREA(x,y) ((x)*(y))
```

5. [was #6]

(a) The call of `putchar` expands into the following statement:

```putchar(('a'<=(s[++i])&&(s[++i])<='z'?(s[++i])-'a'+'A':(s[++i])));
```

The character `a` is less than or equal to `s` (which is `b`), yielding a true condition. The character `s` (which is `c`) is less than or equal to `z`, which is also true. The value printed is `s-'a'+'A'`, which is `D` (assuming that the character set is ASCII).

(b) The character `a` is not less than or equal to `s` (which is `1`) so the test condition is false. The value printed is `s`, which is `2`.

7. [was #8]

(a)

```long long_max(long x, long y)
{
return x > y ? x : y;
}
```

The preprocessor would actually put all the tokens on one line, but this version is more readable.

(b) The problem with types such as `unsigned` `long` is that they require two words, which prevents `GENERIC_MAX` from creating the desired function name. For example, `GENERIC_MAX(unsigned` `long)` would expand into

```unsigned long unsigned long_max(unsigned long x, unsigned long y)
{
return x > y ? x : y;
}
```

(c) To make `GENERIC_MAX` work with any basic type, use a type definition to rename the type:

```typedef unsigned long ULONG;
```

We can now write `GENERIC_MAX(ULONG)`.

12. [was #10] (c) and (e) will fail, since `M` is defined.

14. [was #12; modified] Here's what the program will look like after preprocessing:

```Blank line
Blank line
Blank line
Blank line
Blank line
Blank line
Blank line

int main(void)
{
int a[= 10], i, j, k, m;

Blank line
i = j;
Blank line
Blank line
Blank line

i = 10 * j+1;
i = (x,y) x-y(j, k);
i = ((((j)*(j)))*(((j)*(j))));
i = (((j)*(j))*(j));
i = jk;
puts("i" "j");

Blank line
i = SQR(j);
Blank line
i = (j);

return 0;
}
```

Some preprocessors delete white-space characters at the beginning of a line, so your results may vary. Three lines will cause errors when the program is compiled. Two contain syntax errors:

```int a[= 10], i, j, k, m;
i = (x,y) x-y(j, k);
```

The third refers to an undefined variable:

```i = jk;
``` 