C Language Cheatsheet
This is a C language cheatsheet I made, tailored to the ENGG1110 Problem Solving by Programming class. I believe this class is a foundational course for all engineering students. I think it may be of help to others who enter the course with some prior knowledge of programming, and just need to pick up some C. Personally, it was all that was necessary for a good grade (A) in the course, but results may vary of course.
It's worth noting that the notes are not very organised nor does it follow the curriculum structure, it's just bits and pieces of information I thought worth recording. However, all content does pertain to what was taught.
Notes
int x = 5.99=>x = 5- Remember that characters are actually 1-byte integer values that represent an ASCII character.
- So, char a = "A" actually has an int value of 65 according to the ASCII table.
- Type-casting a float to an integer performs a floor operation on the value.
- e.g.
(int) 0.99 + 5=>5
- e.g.
- Any variables declared within the initialisation of the for loop and its body is scoped to the loop.
- However, the initialisation may make use of a variable declared in the outer scope.
int i=0; for (i=1; i<3; i++) { printf("%d ", i); } printf("%d", i); // result is: "1 2 3"
- However, the initialisation may make use of a variable declared in the outer scope.
- The escape character
\is not regarded as its own individual character. Only the escape sequence in its entirety is regarded as a single character.length("\\a"); // results in a string of length 2 (because the printed string is "\a")- They also occupy the same index within a character array.
- By default, C uses pass by value for all arguments (except arrays, which practically pass by reference)
- When it comes to arrays
- Instead of passing a copy of the array, a pointer to the first element of the array is passed (array decay -> the array variable decays into a pointer, so information about the array is lost like size)
void myFunction(int *arr) { // Equivalent to passing int arr[] }- When you modify the passed array (either through pointer arithmetic or indexing), it changes the original array. So in effect, it's pass by reference.
- The name of an array itself can be treated as a pointer to its first element (
arr = &arr[0]). However, there are still some differences. It is not entirely equivalent. Generally, in an expression, the array name decays to a pointer to the first element of the array, excluding its use insizeof(returns size of entire array in bytes) and unary&(int (*ptr_to_array)[5]=&array_size_5points to the entire array.
- When it comes to arrays
- When the size of an array is not stated, it is initialised to fit the initial declaration.
- You have misunderstood the order of precedence and associativity in C.
- Precedence tells us which operator comes first, and associativity tells us the direction in which operators of the same level are evaluated.
- E.g.
double x = 5 / 2 * 4.0/and*are on the same order of precedence, hence the expression is evaluated from left to right.
- Be wary of integer divisions and floating-point divisions.
double x = 5.0 / 2 * 4.0results in10.0because5.0/2is a floating-point division which results in2.5.double x = 5 / 2 * 4.0results in8.0because5/2is integer division, which results in2.
- In C,
0is regarded as false, and all other non-zero values are regarded as true (including doubles & integers). - Format Specifiers in C
%dor%ifor signed integers%ffor floating-point values, defaults to printing to the 6-th decimal place.%.xfwherexis an integer results in printing a floating-point value to the x-th decimal place.x=0results in an integer result.%cfor a single character%sfor a string/(array of characters).%ufor unsigned integers%%to print a literal percentage sign- Use of whitespace
%cskips leading whitespace and reads the first non-whitespace character%creads any character, skips trailing whitespace until non-whitespacescanfreads the input buffer character after character, sequentially, including\nwhen the user presses enter
- Escape Sequences in C
\nnext line\thorizontal tab\\backslash character- There are many more, not just the ones stated here. So be wary of that.
- Strings
- The ASCII value of
0is theNULcharacter, which is the string terminator\0.- It is not included when we call
strlen. However, in the actual size of the character array, it has to be taken into account. - For example, if we want a string of at most 100 characters, we need to declare an array of size 101 to include the string terminator
- It is not included when we call
- Reading a string
char str[100]; scanf("%s", str); // notice that prefix & is not needed for strings because of array decay- Functions
strlen(str1) -> length of stringstrcpy(dst, src)strcat(dst, src)(appendssrcto end ofdst)strcmp(str1, str2) -> 0 : identical; <0 : first non-matching character in str1 less than corresponding character in str2; >0 : vice versa
- The ASCII value of
- Note that type-casting takes precedence over calculations.
- E.g.
double a = -3.6; printf("%d\n", (int) (a + 0.5)); printf("%f\n", (int) a + 0.5); ```- The above code results in '-3' and '-2.500000'.
- '-3' : it first calculates the result in a+0.5, and then type-casts the result to an int.
- '-2.500000' : following precedence, it first type-casts a to an int (
-3) => -3 + 0.5 = -2.5
- Size of data types
- Integer - 4 bytes
- Float - 4 bytes
- Double - 8 bytes
- Character - 1 byte
- Extracting each digit from an integer
int a; int n = 3; scanf("%d", &a); for (int i=0; i<n; i++) { printf("%d\n", a % 10); a /= 10; if (a <= 0) { i = n; } }
- Postfix and Prefix Increment/Decrement
++variable- Variable is incremented before its value is used in the expression.
- Result of the expression is the incremented value of the variable.
variable++- The variable's current value is used in the expression first.
- The variable is then incremented after its value has been used.
- The result of the expression is the original value of the variable before the increment.
- An assignment operation evaluates to the newly assigned value
- x=5 => 5
- z = 0 => 0
- x+=5 => x=x+5 => x+5
- Function Prototype or Forward Declaration in C
- This is a statement that describes a function's details (name, parameters, return type) before its definition.
- It's used when you want to reference or call a function before its definition in your source code.
#include <stdio.h> int sum(int x, int y); int main(void) { int Sum = sum(x, y); return 0; } int sum(int x, int y) { return x+y; }- Because it's troublesome to maintain, it should only be used when necessary.
- ASCII Table Non-Printable Characters (definitions)
-
- NUL : String-terminator/Null-character/'\0'
-
- SOH :
-
- Remember that array declarations are as such
char name[5]
char getchar(void)- This function has no parameters. It reads the first character entered into the input stream and returns it.
char x = getchar()
- In C, local variables take precedence over global variables when they share the same name within the scope of a function or block. This is known as variable shadowing.
- File IO
- Reading a file
FILE *fptr; fptr = fopen("file.txt", "r"); if (fptr == NULL) { // file failed to open return 0; exit(1); // only when stdlib.h included; alternative } // APPROACH 1 - Controlled Reading char character; for (int i=0; i<10; i++) { fscanf(fptr, "%c ", &character); /* - reads like scanf would but from a file - adding that whitespace "%c " allows us to skip newlines and whitespaces found in the stream */ printf("%c ", character); } // APPROACH 2 - Line after line to the end while (fscanf(fptr, "%c ", &character) != EOF) { printf("%c ", character) } fclose(fptr); ``` fscanfreturns the number of items successfully read. If it reaches the end of file or an input error occurs, a constantEOFis returned. Hence it is our terminating condition in the while loop0can also be returned, which means the input read didn't conform to the type specified by the format specifier.
- Writing to a file
FILE *fptr; fptr = fopen("data.txt", "w"); if (fptr == NULL) return 0; // OR exit(1) fprintf(fptr, "Hello!\n"); for (int i=0; i<10; i++) { fprintf(fptr, "%d ", i); } fprintf(fptr, "\n"); fclose(fptr); /* Content: Hello! 0 1 2 3 4 5 6 7 8 9 */
- Reading a file
fgets(char_array_to_store_into, max_characters, input_stream)- Reads at most
max_characters-1or until a newline character appears. The newline is included in the character array. It also automatically appends a null terminator.
- Reads at most
scanffor string reading- Only includes up to the first whitespace character, unlike
fgets
- Only includes up to the first whitespace character, unlike
- In C, you cannot directly assign one array to equal to another. For character arrays, use
strcpyif necessary. Ormemcpy(dest_arr, src_arr, sizeof(src_arr)) - Structures
struct student { char id[11]; char name[40]; double gpa; // int day, month, year; (acceptable) }; struct student peter; peter.id = "1155123456"; peter.name = "Peter Pennyworth"; peter.gpa = -1.5; struct student amanda = {"1155325932", "Amanda the Baboon", 3.2}; struct student amanda_cpy; amanda_cpy = amanda; // copies info over typedef struct { double lat, lng; } GeoLoc; struct place { char name[200]; GeoLoc centre; }; struct place HK = {"Hong Kong", {22.28, 114.17}}; // this is also valid- When referencing a user-defined struct data type, we need to include this :
struct defined_name, it cannot just be the name we defined, unless we create atypedef. typedef struct type_name alias_name- Defines an alias for any existing type
- Structs are also pass by value into a function unless a pointer is used.
- Macro
#define MAX_COUNT 30- Defines a referenceable constant
- Pointers
// pointers are a distinct data type in C, declared using *ptr_name int n = 3; int *p = &n; // &variable -> address of variable (referencing) // to change address of existing pointer is p = &newaddress printf("%d\n", *p); // *ptr -> dereferencing pointer -> value at pointed address // p = &n (stores in p the memory address of n); *p = n (accesses value in memory address stored in p); printf("%d, %d\n", p, &n); // OUTPUT : address of n twice *p = 0; // manipulates n printf("%d", n); // n = 0 int **ptr = &p; // pointer to a pointer - Dynamic Memory Allocation
malloc(size_in_bytes)- This function allocates a single block of contiguous memory at runtime according to the size specified. Note that it is in bytes.
- Hence, we usually use
sizeof(data_type) * no_of_elementsfor its parameter.sizeof(data_type)returns the size of the data type we specify in bytes. E.g.m (int) -> 2 bytes,sizeof(char) -> 1 byte - It can return
NULLif allocations fails. So we ensure we check for that condition. - The function returns a pointer to the allocated memory, which is inherently void, so we need to perform type casting.
- The allocated memory is not initialised, hence filled with garbage values. So it shouldn't be read without writing to it.
#include <stdio.h> #include <stdlib.h> int main(void) { int numOfGrades; printf("Enter the number of grades: "); scanf("%d", &numOfGrades); char *grades = malloc(sizeof(char) * numOfGrades); // -> returns a pointer to the base address of the allocated memory, equivalent to returning a pointer to the start of the array that we want if (grades == NULL) { // ESSENTIAL, avoids segmentation faults return 1; } for (int i=0; i<numOfGrades; i++) { printf("Grade #%d: ", i+1); scanf(" %c", &grades[i]); // " %c"; whitespace is needed to avoid capturing the newline character that enters the input stream when we enter numOfGrades and type "ENTER". } for (int i=0; i<numOfGrades; i++) { printf("Grade #%d: %c\n", i+1, grades[i]); // we do not need to do *grades[i] here because dereferencing is implied } free(grades); // essential to free the memory locations (since we're just "borrowing it") to avoid memory leaks grades = NULL; // avoids a dangling pointer that would point to deallocated memory return 0; }
- Static Variables
- Static variables are initialised only once, and retain their value between function calls.
- Example 1
int fun() { static int count = 0; count++; return count; } int main() { printf("%d ", fun()); printf("%d ", fun()); return 0; } // OUTPUT: 1 2
- It's not destroyed upon function return
int i, j, x = 5doesn't initialise all three variables to5like Python would. It declaresi, jand only initialisesxto 5. The others would be garbage values.- Width specifier
- In
printf- It specifies the minimum number of characters the output should occupy. If the output given is shorter than the minimum width, the output will be padded by whitespace.
- E.g.
printf("%5d\n", 42) // OUTPUT: " 42"
- In
scanf- It specifies the maximum number of characters to be read
scanf("%5d", &n); // reads at most 5 digits
- In