Skip to content

Instantly share code, notes, and snippets.

@Ellpeck
Last active December 1, 2023 14:44
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Ellpeck/6a08274b6f88636dbc3a7d3ed7afcbc7 to your computer and use it in GitHub Desktop.
A cheat sheet that I use for C programming
// Basically imports
// <> import something from a standard library location
// "" import something from an actual path
#include <stdio.h>
#include <stdlib.h>
// Preprocessor instructions with ifdef and ifndef, needs endif at the end
// ifndef = if not defined
#ifndef OOF
// Define a variable just to do the if check
#define OOF
// Define a variable to be replaced in source code
// This means that BUFFER_SIZE will be replaced by 16 everywhere on compile
#define BUFFER_SIZE 16
#endif
// Pointers can be useful for pass by reference
// addNum takes a poiner and increases the value at its memory location
void addNum(int *a) {
*a += 20;
}
void usePassByReference() {
int x = 10;
// Calling addNum with the location of the variable will increase it
// without having to return the changed value later
addNum(&x);
// meaning that x will be 30 here, not 10 like it would be without pointers
printf("x is %d\n", x);
}
// Function pointers exist!
void someMethod(int d) {
printf("d is %d\n", d);
}
// You can create a function pointer with a return type (in this case void)
// and a variable name (in this case "function") that takes a certain number
// of parameters (in this case one integer, so "(int)")
void callAMethodWithAnIntParam(void (*function)(int), int parameter) {
// You can then call the function that the pointer points to by doing this
// and giving it the parameters like with a normal function
(*function)(parameter);
}
void useFunctionPointers() {
//Now these two calls do the same, basically
someMethod(10);
callAMethodWithAnIntParam(someMethod, 10);
}
// Static function variables
// Much like in Java, static variables stay put
// But the difference here is that you can actually have static variables
// in methods that still stay
int addToSum(int add) {
static int sum = 0;
// Calling this method will add to the total sum
sum += add;
return sum;
}
// Structs to store more data at once
struct vec2 {
double x;
double y;
};
void useStruct() {
// When making a variable of a struct, you still have to put "struct" in front
struct vec2 point;
// When making a struct variable, you can directly set its data without
// having to call a constructor or anything
point.x = 10.0;
point.y = 20.0;
// Structure pointers can be useful for linked lists etc.
struct vec2 *pointRef;
// Instead of using ., you can use -> to access the value of a structure
// pointer. The call below is equivalent to the call (*pointRef).x = 0.25;
pointRef->x = 0.25;
pointRef->y = 0.5;
printf("point is %.2f, %.2f\n", point.x, point.y);
printf("pointRef is %.2f, %.2f\n", pointRef->x, pointRef->y);
}
// Enums to make a list of things
enum color {
RED, BLACK
};
void useEnum() {
// When making a variable, you still have to put "enum" in front
// Assignment also possible using integers (enums are just integers basically)
enum color c = RED;
printf("c is %d\n", c);
}
// Typedef allows you to define an actual type based on a struct or enum
// To use typedef, you need the first argument to be the thing you want to
// define a type of, and the second argument ("vec3") to be the name of the
// new type
typedef struct vector3 {
double x;
double y;
double z;
} vec3;
// Type definition like this has multiple parts:
// struct vector3 { double x; double y; double z; } is the struct itself
// typedef <something> <name> makes it so that you don't have to write "struct vector3 point;" to create a variable
// These two can be combined into the following to make it shorter as well:
typedef struct {
double x;
double y;
} vec2;
// You can also define a type that just mirrors another one
typedef int address;
void useTypedef() {
// Creating variables of structs
vec3 point;
point.x = 5.0;
point.y = 10.0;
point.z = 0.0;
printf("point is %.2f, %.2f, %.2f\n", point.x, point.y, point.z);
// Creating variables of custom types
address testAddress;
testAddress = 7;
}
// The main method that gets called when executing the program
// Receives the amount of arguments and an array of arrays of chars
// (so an array of strings) which stores the actual arguments
int main(int argumentAmount, char **arguments) {
// Prints something out to the console
// f stands for formatted -> you can use %s etc to format your output
printf("Hello World my dudes\n");
// sizeof gets the size of a data type - so the amount of bytes it takes up
// This can also be done on a malloc'd array to find the size in bytes
// directly!
int size = sizeof(int);
// Unsigned variables
unsigned int i = 10;
// There are no boolean data types
// Doing an if check with an integer will return
// true if the integer is != 0, false otherwise
int booln = 0;
// Pointers: They're confusing, so strap in
int c = 0;
// Pointer variable intialization - d is going to point to something
// rather than be something
int *d;
// & is the referencing operator - it gives back the address of a variable
// In this case, d will not be set to c = 0, but to the address where the 0
// sits in memory
d = &c;
// d is pointing to an address in memory that stores a value (in this case
// the address that stores the 0 that c was assigned to)
// * is the dereferencing operator - it gives back the value at an address
// In this case, c will be set to 0, because d points to its address
c = *d;
// Array arithmetics work as you'd want them to
// This creates an array for 16 ints, so 16*sizeof(int) bytes of storage
int array[16];
// If you increase the value of a pointer, then it will shift the address
// in memory that it looks at - by the amount of bytes of its type
// In this case, pointer will be moved by sizeof(int) bytes, not just one!
int *pointer;
pointer++;
// Allocates space that shouldn't be overriden by something else
// This is useful if you want an array that you fill later
// Keep in mind that this is only necessary for arrays!
// malloc(x) reserves x bytes
char *buffer = malloc(sizeof(char) * BUFFER_SIZE);
// After you're done with the data, free the memory for different use
free(buffer);
usePassByReference();
useFunctionPointers();
useStruct();
useEnum();
useTypedef();
}
@denisenepraunig
Copy link

Really nice overview! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment