James (Siyuan) Guo     Home | CV | Research | Notes | Projects | Teaching | Blogs | Contact



Basic C Notes

Linux System:

Introduction to Linux Environment:

Linux Basics:

Basic Linux Commands:

Basic Commands:

File Redirections:

Git Workflow:

Introduction to Git:

Git Basics:

Git File Types:

Git Commands:

Git Tasks:

Git Command Orders:

C Compiler:

C Structure:

C programming files:

.h file in C:

// rectangle.h:  
// include lines like this at the top; change the all-caps
// name to match the file name, rectangle.h in this case

#ifndef RECTANGLE_H  

#define RECTANGLE_H

struct rectangle { // structure
	int height;
	int width;
};

// include this line at the bottom

#endif

Makefile in C:


# Makefile:

CC=gcc  
CFLAGS=-std=c99 -pedantic -Wall -Wextra

main: mainFile.o functions.o  
	$(CC) -o main mainFile.o functions.o

mainFile.o: mainFile.c functions.h
	$(CC) $(CFLAGS) -c mainFile.c

functions.o: functions.c functions.h
	$(CC) $(CFLAGS) -c functions.c

clean:  
	rm -f *.o main

C Compiling Process:

Steps of Compiler in C:

C Compiling Command:

C Debugging Process:

GNU debugger, GDB:

Memory Track, valgrind:

C Libraries:

stdio Library:

math Library:

assert Library:

string Library:

ctype Library:

stdlib Library:

C Variables and Functions:

Variables in C:

Data Types in C:

Variable Type Conversion:

Declaring and Initializing Variables:

Operators and Precedence in C:

Functions in C:

Function definitions:

<retur_type> <function_name>(<input_type> <input_name>, ...) {
	// Code in between.
	return <value>;
}

The main function:

int main() {
	// Code in between.
	if (condition) return 1; // return non-zero value to indicate error code.
	return 0; // return zero for success.
}
int main(int argc, char* argv[]) {
	// Code in between.
	return 0; // return zero for success.
}

Recursive Functions:

Pseudo-random in C:

Code Range of values (inclusive)
rand() 0 to RAND_MAX
rand() % x 0 to x-1
(rand() % x) + y y to y+x-1
(rand() % x) / (double) x 0.0 to \(1.0-\frac{1}x\)
rand() / (double)(RAND_MAX) 0.0 to 1.0

#include <math.h>

int randomNormal() {
	int max_limit = 100;
	double num = 0.0;
    for (int i = 0; i < max_limit; i++) {
	    num += rand() - (RAND_MAX / 2.0f); // Increment by sum.
    }
    return (int) (num / max_limit); // Returns normally distributed integer.
}

Types of Variables:

Scope and Lifetime:

Local (or Stack) Variable:

Static Variable:

Global Variable:

Control and Flow:

Conditional:

if (condition_1) {  
	// Code for condition_1.
}
else if (condition_2) {
	// Code for condition_2.
}
else {
	// Code for else.
}
condition ? /* code for true */ : /* code for false */ ;
switch (integer_expr) {
case c1: stmt1; // execution starting point for c1
case c2: stmt2;
		 break; // exits switch block
case c3:  
case c4: stmt3;
		 stmt4; // executes stmt3, stmt4 and stmtlast for matches of c3 or c4
default: stmtlast; // if no case matches
}

Loops:

while (boolean_expression) { /* statements */ }
do { /* statements */ } while (boolean_expression);
for (initialize; boolean_expression; update) { /* statements */ }

C Input and Output:

File* Pointer:

fopen Function:

Other Open Functions:

Standard Structure for fopen:

// file_io_loop_eg.c:


#include <stdio.h>
int main() {
	FILE* input = fopen("numbers.txt", "r"); if (input == NULL) {
		fprintf(stderr, "Error: could not open input file\n");
		return 1; // indicate error
	}
	
	int a = 0, b = 0;  
	int numCollected = fscanf(input, "%d%d", &a, &b);
	
	while (numCollected == 2) {
		printf("%d\n", a+b);
		numCollected = fscanf(input, "%d%d", &a, &b);
	}
	
	if (ferror(input)) {  
		fprintf(stderr, "Error: error indicator was set for input file\n");
		return 2; // indicate error
	} else if (numCollected != EOF) {
		fprintf(stderr, "Error: could not parse line\n");
		return 3; // indicate error
	}
	
	fclose(input); // Close input file return 0; // no error
	return 0;
}

Program Output:

printf for output:

Placeholder Letter Placeholder Type
d decimal (integer type, ld for long int)
u unsigned (integer type that disallows negatives, lu for long unsigned)
f floating point (float, lf for double)
c character
s string

fprintf for output:

sprintf for output:

fwrite for output:

Program Input:

scanf for input:

Placeholder Letter Placeholder Type
d decimal (integer type, l for long)
u unsigned (integer type that disallows negatives, lu for long unsigned)
c character
f floating point (float, lf for double)
s string (default reads to a space)
char dummy = '\0';
while (dummy != '\n') {
	if (scanf("%c", &dummy) == -1) {
		break;
	}
}

fscanf for input:

sscanf for input:

fread for input:

Arrays and Pointers in C:

Arrays:

1D Arrays:

Strings:

const char str[] = "text";
char str_copy[sizeof(str)];  
for(int i = 0; i < sizeof(str); i++) {
	str_copy[i] = str[i];
}

Multi-dimensional Arrays:

Arrays in functions:

Pointers:

Pointers in C:

Pointer Arithmetics:

Dynamically Allocation:

// Allocating space for size data_type on heap
<data_type> *ptr = malloc(sizeof(<data_type>) * size);
// Check if allocation succeeded
if (ptr == NULL) { /*output error message*/ }
// Free the pointer after use
free(ptr);
// Allocating space for size data_type on heap
<data_type> *ptr = calloc(size, sizeof(<data_type>));
// Check if allocation succeeded
if (ptr == NULL) { /*output error message*/ }
// Free the pointer after use
free(ptr);
// reallocate to expand or contract
ptr = realloc(ptr, sizeof(<data_type>) * new_size);

Multi-dimensional Arrays by Dynamic Allocation:

// Declaring and initializing the double pointer.
<data_type> **ptr = malloc(sizeof(<data_type>*) * num_rows);

// Fill in each pointer with pointer.
for (int i = 0; i < num_rows; i++) {
	a[i] = malloc(sizeof(<data_type>) * num_cols);
}

const Protection for Pointers:

struct in C:

Introduction to struct:

Defining struct:

struct card {
	// Fields
	int rank;
	char suit;
};
struct <struct_name> <var_name>;  // Declaring a struct
<var_name> = { ... }; // Initialize struct as arrays.
typedef struct {
	struct {   // Unnamed structure.
        int r; // Fields in this struct.
        int b;
        int g;
	} color;
	struct {   // Second Unnamed structure.
		int x;
        int y;
    } position;
} pixel;

Struct and Functions:

Linked Lists:

Linked List as a Data Structure:

typedef struct _node {
	char data;
	struct _node *next;
} Node;
Array Linked List
size of the array is fixed sized of linked list is not fixed
occupies less memory for the same number of elements requires more space because of “next”
accessing \(i\)-th value is fast using indices (simple arithmetic) has to traverse the list from start
inserting new elements is expensive after deciding where to add, is straightforward (no shifting)
no deleting without shifting items deleting is easy (kind of)

Functions in Linked List:

// Print all the elements in the linked list
void print(const Node * cur) {
	while (cur != NULL) {
		printf("%c ", cur->data);
		cur = cur->next; // advance to next node
	}
}
// Get the length of nodes in a linked list
long length(const Node * head) {
	if (head == NULL) return 0; // Base case, return 0
	return 1 + length(head->next);
}
// Add a new node to linked list
void add_after(Node * node, char val) {
	if (node == NULL) return;
	Node * n = create_node(val);
	n->next = node->next;
	node->next = n;
}
// add node to beginning of list
void add_front(Node ** list_ptr, char val) {
	Node * n = create_node(val);
	n->next = *list_ptr;
	*list_ptr = n;
}
// remove node after current, return removed char, or '?' if no node
char remove_after(Node * node) {
	char rmd_value = '?';
	if (node->next == NULL) return rmd_value;
	Node * ptr = node->next->next;
	rmd_value = node->next->data;
	free(node->next);
	node->next = ptr;
	return rmd_value;
}
// remove first node, if any, return removed char or '?' if no node
char remove_front(Node ** list_ptr) {
	char rmd_value = '?';
	if ((*list_ptr) == NULL) return rmd_value;
	Node * ptr = (*list_ptr)->next;
	rmd_value = (*list_ptr)->data;
	free(*list_ptr);
	*list_ptr = ptr;
	return rmd_value;
}
// remove all occurrences of a particular character
void remove_all(Node ** list_ptr, char val) {
	if (*list_ptr == NULL) return;
	if ((*list_ptr)->data == val) {
		remove_front(list_ptr);
		remove_all(list_ptr, val);
	} else {
	remove_all(&((*list_ptr)->next), val);
	}
}
// free all the nodes
void clear_list(Node * list_ptr) {
	if (list_ptr->next == NULL) {
		free(list_ptr);
	} else {
		clear_list(list_ptr->next);
	}
}



🌞
If you find any questions, please contact me via Contact tab.