# Warm-up

Declare a 3-d array of 2x2x3 `int`s and statically initialize it with numbers 1..12. Retype the array as 1-d and print all elements. You should get then:

``````\$ ./a.out
1 2 3 4 5 6 7 8 9 10 11 12
``````

# The last initializer and a comma

In C89, having a comma after the last initializer was a syntax error. Since C99, it's optional.

```struct s {
int a;
int b;
} s = { 1, 2, };	// ',' after 2 is optional```

See why keeping the last comma always there might be a very good idea: 👀 missing-comma-in-initializer.c

# Enumeration constant

We already know integer constants, character and string constants, a floating-point constant, constant expression (an expression that involves only constants).

There is one other kind of constant, the "enumeration constant". An enumeration is a list of constant integer values, as in:

`enum boolean { NO, YES};`

The first name has value `0`, the next one `1`, etc. You can use explicit values as well. Unspecified values continue to progress from the last value specified. For example:

```enum months {
JAN = 1,
FEB,
MAR,
APR,
MAY,
JUN,
JUL,
AUG,
SEP,
OCT,
NOV,
DEC,
};```

You could also do as follows:

```enum weird {
one = 3,
two,		// 4
three = 3,
four = 0,
five,		// 1
six,		// 2
seven = -1,
...
}```

The list consists of enumerators. I.e. both `JAN = 1` and `FEB` are enumerators. When used in code, `JAN`, `FEB`, `MAR` etc. are enumeration constants. The values of enumeration constants must fit an `int`. However, the implementation may define any integer type to be compatible with the enumerated type under the condition that all enumeration constants fit the type. So, the implementation might choose a `char` to be compatible with the `enum boolean` above.

`enum white_space { NL = '\n', SP = ' ', TAB = '\t' };`

The `sizeof` operator applied on an enum itself tells you the integer type used (`sizeof (enum weird)`), and `sizeof` on any enumeration constant gives you the same number.

Names in different enumerations must be distinct. In other words, all enumerators share the same name space. Values in the same enumerations need not be distinct, e.g.:

`enum not_really_useful { GGG = 1, HHH = 1, GHGH = 0 };`

Example: 👀 enums.c, enum-values.c

## Use `enum`s!

This:

```enum commands {
XXX_LIST,
XXX_EXTRACT,
XXX_CREATE
}```

is so much better than this:

```#define	XXX_LIST	0
#define	XXX_EXTRACT	1
#define	XXX_CREATE	2```

The reason is that the enum is known to the compiler and may be included into debug symbols. So, when debugging, you might, if the compiler/debugger support it, see `XXX_LIST` instead of just `0`. In the latter case, as the compiler only see the numbers when compiling the code, you will never see any symbolic names. So, seeing the symbols instead of common numbers `0` or `1` is really helping.

# The `const` keyword

`const` is a qualifier that may be applied to the declaration of any variable. It specifies its value cannot be changed. If you apply `const` to an array, the array elements cannot be modified.

You can initialize the variable declared with the `const` qualifier.

Using `const` will not really make the storage constant, you just cannot use that variable for an assignment to the storage.

```int i = 'c';
int const *p2 = &i;

// illegal
*p2 = 'x';
// ok
i = 'x';```

It also depends where you apply the `const` keyword.

```char const *s1;		// s1 is a pointer to const char
const char *s1;		// same as above
char *const s2;		// s2 is a const pointer to a char

*s1 = 'c';		// illegal
s1 = NULL;		// legal

s2 = NULL;		// illegal
*s2 = 'a';		// legal```

Using `const` can get a bit confusing. It is mostly used for pointer arguments to constant memory to specify that an array will not be changed in the function. For example, string functions:

```size_t strlen(const char *s);
char *strncpy(char *dest, const char *src, size_t n);
...```

🔧 `const`

The following is a `const` pointer to a `const` character. So, you can neither do `*p = ...` nor `p = ...`. Verify.

`const char *const p;`

# The `typedef` keyword

• note that a `char`, signed and unsigned integer types, and the floating types are collectively called basic types.
• then you have derived types - an array type, a structure, a union, a function type, a pointer type.

With `typedef`, you create new data type names for existing types. Note that you never create new data types with `typedef`. In other words, with `typedef`, you create synonyms to existing types.

`typedef` is most commonly used for derived types but many C provided names by the standard are based on basic types. For example, `size_t`, see its definition in `/usr/include/sys/types.h`.

`typedef` is used as follows:

```typedef int myint;
typedef *char mycharptr;

mycharptr p = "my string";```

`typedef` is also great to create complex type names in small steps. As we will see next.

```typedef char **array;
array a;```

The convention is to add `_t` to a new type name. For example:

```typedef struct mystruct_s {
int a;
char c;
} mystruct_t;```

And you can use it like this:

```struct mystruct_s x;
mystruct_t y;```

`x` and `y` are of the same type.

Use `typedef` in the warm-up code for the item structure and use the new name instead of `struct item ...`.

# Variable name space and scope

Identifiers fall into several name spaces that do not interfere with one another.

These distinct classes are:

• objects, functions, `typedef` constants
• labels
• tags of structures or unions, and enumerations
• structure or union individually

The "individual" part means each structure or union has its own namespace. So, you can have two different structures, each using the same member names.

To read a complex declaration, you use operator priorities and watch for parentheses.

`char **argv`

`argv` is a pointer to a pointer to `char`

`int (*a)`

`a` is a pointer to an array of 10 `int`s

`int *a`

`a` is an array of 10 pointers to `int`

`void *myfunc()`

`myfunc` is a function returning a pointer to `void`

`void (*myfunc)()`

`myfunc` is a pointer to a function returning `void`

`char (*(*x())[])()`

`x` is a function returning pointer to an array of pointers to a function returning a `char`

`char (*(*x)())`

`x` is an array of 3 pointers to a function returning a pointer to an array of 5 `char`s

1. find the identifier (non keyword or custom type) of a variable or function
2. start decoding:
• left to right
• `)` => reverse decoding direction
• `()` => denotes function
• `[]` => array
• `;` => reverse the direction
• when reading from right to left, we can hit:
• `(` => reverse the direction
• `*` => pointer
• type identifier => starts the whole definition

Example:

`char *(*(**foo[])())[];`

You can mentally simplify as:

`char *(*SOME_FUNCTION)[];`

Where `SOME_FUNCTION` is `(**foo[])()`

`foo` is an array of arrays of 8 pointers to a pointer to a function returning a pointer to an array of pointers to a `char`.

Alternatively, you can do it via two simpler steps:

```typedef char *a_of_p[];
typedef a_of_p *(**foo[])();```

🔧 Practice:

```int *(*(*fp1)(int));
char (*(*x())[])()
double *f()[]           // this is not legal in C as a function cannot
// return an array```

# Bitwise operations

Print `argv` in binary (assume it is a correct decimal number). Note that `printf`(3) does not have a conversion specifier for it (unlike 'x' for hexa and 'o' for octal). Limit the input to positive `int`s. Do not use bit operators even if you know how to (ie. do NOT use `>>` etc.)

To verify, use bc(1) with `obase=2`. E.g.:

``````\$ bc
obase=2
10
1010
255
11111111
2^31-1
1111111111111111111111111111111

\$ ./a.out 2147483647
1111111111111111111111111111111
\$ ./a.out 255
11111111
\$ ./a.out 348508345
10100110001011101000010111001
``````

You can also use `obase=8`, `obase=16`, etc. Note that bc(1) takes only capital letters as digits, ie. use "E4" for 0xe4, not "e4". "e4" is treated as a variable:

``````\$ bc
ibase=16
obase=2
e4
0
E4
11100100
``````

Bitwise operators are as follows:

Operator Meaning
`&` bitwise AND
`|` bitwise OR
`^` bitwise XOR
`<<` left shift
`>>` right shift
`~` one's complement (unary)

Note, individual bits are being processed. I.e.:

``````316 & 978			-> convert to binary to see it
100111100 & 1111010010		-> do logical AND bit by bit now

0100111100
1111010010
----------
0100010000	== 272 (use ibase=2 with bc(1) to verify)
``````

So,

``````((338 & 978) == 272).	// == is of higher prority than &
``````

Common uses of bitwise operators:

```n = n & 01777;			// zero out some highest bits

/*
* Setting individual flags.  Note that each of the flags has
* just one bit set.
*/
#define	LIGHT_OFF	0x0000
#define	LIGHT_GREEN	0x0001
#define	LIGHT_RED	0x0002
#define	LIGHT_BLUE	0x0004
#define	LIGHT_YELLOW	0x0008
#define	LIGHT_VIOLET	0x0010
#define	LIGHT_WHITE	0x0020
// ...

lights = lights | LIGHT_YELLOW;	// turn on yellow light
lights = lights & ~LIGHT_RED;	// turn off red light```

## Binary operators and integer promotion

When working with bitwise operators, operands are promoted the same way as we learned in Conversions and promotions

That means:

``````13U & -1				-> promote int (-1) to unsigned,
i.e.  promote -1 to unsigned.
You get:

13 & 4294967295				-> now convert to binary
1101 & 11111111111111111111111111111111	-> the result clearly is 1101
``````

🔧 Task: rewrite `print-in-binary.c` using bitwise operators

🔧 Task: count 1 bits in a number (`argv`).

``````\$ ./a.out 337
4
\$ ./a.out 13375
9
``````

# 🔧 Home assignment

Note that home assignments are entirely voluntary but writing code is the only way to learn a programming language.

(Note: this assignment was given in one of the previous years as the assignment for the final in-person test with the 90 minute limit).

```/*
* Create a set of functions for manipulating a linked list.  The program
* accepts input commands as command line arguments and executes them.  New
* elements are always appended to the list and any item is always removed from
* the head.  Keep pointers to the first list item (head) and the last one
* (tail).
*
* Commands are: create a list, insert an item, remove an item, and print the
* list.  It is mandatory to create a list before doing anything else.
*
*   create a list:		C
*   insert an item:		I<nnn>
*   remove an item:		R
*   print a list:		P
*
* Do reasonable checking for dealing with invalid input.  See below.
*
* Example:
*
*   \$ ./a.out C I1 I2 I3 I4 I5 P R P I6 P I7 P R P R P R P R R R P I88 P R P
*   List: 1 2 3 4 5
*   List: 2 3 4 5
*   List: 2 3 4 5 6
*   List: 2 3 4 5 6 7
*   List: 3 4 5 6 7
*   List: 4 5 6 7
*   List: 5 6 7
*   List: EMPTY
*   List: 88
*   List: EMPTY
*
*   \$ ./a.out C R
*   a.out: Cannot remove an item from an empty list.
*
*   \$ ./a.out C P
*   List: EMPTY
*
*   \$ ./a.out C L
*   a.out: Wrong command: L
*
*   \$ ./a.out C C
*   a.out: List already created, exiting.
*
*   \$ ./a.out I88
*   a.out: List not created yet.
*/```

## `getbits`()

Implement a function `getbits(x,p,n)` that returns the (right adjusted) `n`-bit field of `x` that begins at position `p`. We assume that bit position `0` is at the right end and that `n` and `p` are sensible positive values. For example, `getbits(x,4,3)` returns the three bits in positions 4, 3 and 2, right-adjusted.

The idea is to zero out anything that is to the left of `p`, then shift those `n` bits to the very right, and you get the result.

```/* 1 0000 0000: should return 1 */
i = getbits(0x100, 8, 1);
(void) printf("0x%X\n", i);
assert(i == 1);

/* 1110 0100: should return 9 */
i = getbits(0xe4, 5, 4);
(void) printf("0x%X\n", i);
assert(i == 9);

/* 1010 1010: should return the same number, ie. 0xAA */
i = getbits(0xAA, 7, 8);
(void) printf("0x%X\n", i);
assert(i == 0xAA);```