Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1Learning Outcomes

Treat this note as reference material until you need it.

1.1typedef

typedef allows you to create an additional name (alias) for another data type.

typedef uint8_t BYTE;
BYTE b1, b2;

The above code defines BYTE as another name for uint8_t, allowing us to declare b1 and b2 both as BYTE type. Side note: We don’t recommend declaring multiple variables within the same value as above; it leads to confusing types when we introduce pointers next time.

1.2Structs

structs are structured groups of variables. A struct is an abstract data type definition. It feels very much like Python where you have a class and dot fields, but you have a lot more control.

Structs and typedefs are often used in tandem. Longer example:

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct {
    uint16_t length_in_seconds;
    uint16_t year_recorded;
} SONG;

SONG song1;
song1.length_in_seconds  =  213;
song1.year_recorded      = 1994;

SONG song2;
song2.length_in_seconds  =  248;
song2.year_recorded      = 1988;

Important:

1.3C Preprocessor Macros, #define

#define PI (3.14159) is a CPP (C Preprocessor) Macro. Prior to compilation, preprocess by performing string replacement in the program based on all #define macros. The line above replaces all PI with (3.14159) and in effect makes PI a “constant.”

You often see CPP macros defined to create small “functions”. But remember that because #define is effectively string replacement, these aren’t actual functions—instead, you are simply changing the text of the program.

Because #define is effectively string replacement, this can produce interesting errors. For example:

#define min(X,Y) ((X)<(Y))
next = min(w, foo(z));

is translated to this code, before compiling:

next = ((w)<(foo(z))?(w):(foo(z)));

If foo(z) has a side effect, that side effect will occur twice!

1.4Constants and Enums

The keyword const declares a constant; the variable is assigned a typed value once in the declaration. You can have a constant version of any of the standard C variable types, but values can’t change during entire execution of program.

const float  golden_ratio = 1.618;
const int    days_in_week = 7;
const double the_law      = 2.99792458e8;

An enum is a nice feature for enumerated constants It declares a group of related integer constraints, like red=0, green=1, blue=2:

enum cardsuit {CLUBS,DIAMONDS,HEARTS,SPADES};
enum color {RED, GREEN, BLUE};

My strong recommendation: don’t peek under the hood to find out what those bits are. Instead, use the abstraction; your code should work even if you rearrange the ordered set.

1.5Control Flow

Very similar to Java. Not much to say here beyond two items:

Curly braces: Bodies of if-else conditionals and loops can be surrounded by curly braces or stand-alone. See the previous section.

While loops: In addition to the standard while loop, C also has the do-while loop:

do statement while (expression);

Switch: Until you reach a break statement, you will continue to execute statements, even those in subsequent cases.

switch (expression){
  case const1:    statements
  case const2:    statements
  default:        statements
}
break;

When writing C code, we don’t recommend the do-while loop, nor the dreaded goto. But we’ll find both ideas useful when we discuss control flow in assembly language. More (much) later.

1.6Functions

Two example functions:

int number_of_people(int class1, int class2) {
  return class1 + class2;
}

float dollars_and_cents (float cost) {  return cost; }

Variables and functions must be declared before use. In older C versions, this meant that all function declarations needed to be at top of files, or included in headers. Function implementations could be described later in the file. In more recent C, functions can be used so long as they are declared in the file.