Unit 5: Input/Output, Files, and Low-Level Programming

Table of Contents

1. Standard Input and Output

This refers to I/O operations from the console (keyboard and screen), which are represented by stdin and stdout.

Formatted Output (printf)

printf ("print formatted") is used to print data to the screen. It uses format specifiers (like %d) to indicate how to print a variable.

printf is a variable length argument function, meaning it can take a different number of arguments each time it's called. This is made possible by the ... (ellipsis) syntax, handled by the library.

Formatted Input (scanf)

scanf ("scan formatted") is used to read data from the keyboard. It uses the same format specifiers as printf.

You must pass the address (using &) of the variable you want to fill.
int age;
scanf("%d", &age); // Correct
scanf("%d", age);  // WRONG: Will crash
The only exception is for strings (char arrays), which do not need & because the array name *is* an address.
char name[50];
scanf("%s", name); // Correct

2. Data Files

File handling allows your program to read from and write to files on the disk, making data persistent. All file operations use a special pointer: FILE *fp;.

Opening and Closing Files (fopen, fclose)

You must open a file before you can use it. fopen() returns a FILE pointer, or NULL if it fails.

FILE *fp = NULL;
// Open "data.txt" for writing ("w")
fp = fopen("data.txt", "w"); 

if (fp == NULL) {
    printf("Error opening file!\n");
    return 1; // Exit
}
// ... do file operations ...

// Always close the file when done
fclose(fp);

Common File Modes:

Processing Files (Formatted vs. Unformatted)

Miscellaneous Functions

3. Low-Level Programming

This involves operations that are closer to the hardware, often manipulating individual bits.

Register Variables

This is a repeat from Unit 2. The register keyword suggests to the compiler that a variable should be stored in a CPU register for faster access. It's often used for loop counters, but modern compilers are smart enough to do this automatically.

Bitwise Operations

These operators work on the binary (bit) representation of integers.

OperatorNameExample (a=5, b=3)Result
& Bitwise AND 0101 & 0011 0001 (1)
| Bitwise OR 0101 | 0011 0111 (7)
^ Bitwise XOR 0101 ^ 0011 0110 (6)
~ Bitwise NOT ~0101 1010 (-6)
<< Left Shift 0101 << 1 1010 (10)
>> Right Shift 0101 >> 1 0010 (2)
Uses: Setting/checking a specific bit (e.g., flags), high-speed multiplication/division by 2, encryption.

Bit Fields

Bit fields allow you to define structure members that are only a specific number of bits wide. This is used to pack data tightly, often for hardware programming.

// This structure packs a date into 16 bits (2 bytes)
struct Date {
    unsigned int day : 5;  // 5 bits (can hold 0-31)
    unsigned int month : 4; // 4 bits (can hold 0-15)
    unsigned int year : 7;  // 7 bits (can hold 0-127)
};

Enumeration (enum)

An enumeration is a user-defined type that consists of a set of named integer constants. It makes code more readable.

// Define an enum for days of the week
enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN };

int main() {
    // By default, MON=0, TUE=1, WED=2, ...
    enum Weekday today = WED;
    
    if (today == 2) { // Works, but less readable
        //...
    }
    if (today == WED) { // Much better
        //...
    }
    return 0;
}

4. Other Topics

This unit re-lists several topics from previous units, likely for reinforcement.

Command Line Arguments

See Unit 3 notes. This refers to int main(int argc, char *argv[]) for receiving arguments when the program is executed.

Library Functions & Preprocessor