Skip to content

Instantly share code, notes, and snippets.

@codec4
Forked from Ellpeck/c.c
Created September 6, 2024 09:13
Show Gist options
  • Select an option

  • Save codec4/c6ea0ceb7405fc9cd44709b9c23ecca8 to your computer and use it in GitHub Desktop.

Select an option

Save codec4/c6ea0ceb7405fc9cd44709b9c23ecca8 to your computer and use it in GitHub Desktop.

Revisions

  1. @Ellpeck Ellpeck revised this gist Oct 26, 2020. 1 changed file with 85 additions and 72 deletions.
    157 changes: 85 additions & 72 deletions c.c
    Original file line number Diff line number Diff line change
    @@ -1,43 +1,43 @@
    //Basically imports
    //<> import something from a standard library location
    //"" import something from an actual path
    // 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
    // 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 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 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
    // 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
    // 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
    // meaning that x will be 30 here, not 10 like it would be without pointers
    printf("x is %d\n", x);
    }

    //Function pointers exist!
    // 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)")
    // 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
    // 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() {
    @@ -46,121 +46,134 @@ void useFunctionPointers() {
    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
    // 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
    // Calling this method will add to the total sum
    sum += add;
    return sum;
    }

    //Structs to store more data at once
    // 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
    // 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
    // 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.
    // 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;
    // 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
    // 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)
    // 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 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() {
    //You can then just make variables like this, without having to put the type
    // 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
    // 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
    // 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!
    // 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 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
    // 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
    // Pointers: They're confusing, so strap in
    int c = 0;
    //Pointer variable intialization - d is going to point to something
    //rather than be something
    // 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
    // & 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
    // 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
    // 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!
    // 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
    // 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
    // After you're done with the data, free the memory for different use
    free(buffer);

    usePassByReference();
  2. @Ellpeck Ellpeck created this gist Oct 26, 2020.
    171 changes: 171 additions & 0 deletions c.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,171 @@
    //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;
    void useTypedef() {
    //You can then just make variables like this, without having to put the type
    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);
    }

    //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();
    }