1Learning Outcomes¶
Treat this note as reference material until you need it.
Navigate the large laundry list of C topics here, and use the K&R reference to fill in details.
Pay special attention to
typedefandstruct, which are used to declare and organize more complex data types.
🎥 Lecture Video
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 12typedef 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;
Code, explained
Lines 1 - 4
SONGis an alias fortypedef struct {int length_in_seconds; int year_recorded; }Line 6: Declare
song1as a struct that has twouint16_tvariables,length_in_secondsand `year_recorded.Line 7-8: Instantiate the data within the
song1variable.Lines 10-12: Do something similar for
song2.
Important:
Structs are not objects.
The dot (
.) operator is therefore not a method call; it merely accesses data at a specific location. More later.
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; }You have to declare the type of data you plan to return from a function.
The
returntype can be any C variable type (orvoid), and is placed to the left of the function name. Thevoidreturn type implies that no value will be returned; we return to this later in the course.Parameters also must be typed.
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.