{"id":18111638,"url":"https://github.com/laymer/upgraded-potato","last_synced_at":"2025-04-06T08:21:42.593Z","repository":{"id":67405044,"uuid":"441215407","full_name":"Laymer/upgraded-potato","owner":"Laymer","description":"Learning C programming again for fun :)","archived":false,"fork":false,"pushed_at":"2022-01-09T15:29:05.000Z","size":149,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-12T13:56:47.688Z","etag":null,"topics":["c","fun","learning","networks","programming"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Laymer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-23T15:05:26.000Z","updated_at":"2023-03-08T02:54:07.000Z","dependencies_parsed_at":"2023-02-21T19:31:13.405Z","dependency_job_id":null,"html_url":"https://github.com/Laymer/upgraded-potato","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laymer%2Fupgraded-potato","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laymer%2Fupgraded-potato/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laymer%2Fupgraded-potato/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laymer%2Fupgraded-potato/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Laymer","download_url":"https://codeload.github.com/Laymer/upgraded-potato/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247452738,"owners_count":20941161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","fun","learning","networks","programming"],"created_at":"2024-11-01T01:06:58.032Z","updated_at":"2025-04-06T08:21:42.577Z","avatar_url":"https://github.com/Laymer.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The upgraded-potato\nLearning C programming again for fun :)\n\n\u003cimg src=\"https://yt3.ggpht.com/a/AGF-l79REyhoc8SBId2NuI6fb7bUpodJz4tGKjYgNQ=s900-c-k-c0xffffffff-no-rj-mo\" data-canonical-src=\"https://yt3.ggpht.com/a/AGF-l79REyhoc8SBId2NuI6fb7bUpodJz4tGKjYgNQ=s900-c-k-c0xffffffff-no-rj-mo\" width=\"400\" height=\"400\" /\u003e\n\n## Random notes I found interesting\n\n* [Character Conversion](#character-conversion)\n    *   [Leading blank for `scanf()`](#leading-blank-for-scanf)\n* [Operators](#operators)\n    *   [Ternary operators](#ternary-operators)\n    *   [Unary operators](#unary-operators)\n* [Pointers](#pointers)\n    *   [Pointers to struct fields](#pointers-to-struct-fields)\n    *   [\"Address of\" and \"value of\" operators](#address-of-and-value-of-operators)\n    *   [Initializing arrays of integers](#initializing-arrays-of-integers)\n* [Threads and Procs](#threads-and-procs)\n    *   [Why does a printf after `fork()` display twice?](#why-does-a-printf-after-fork-display-twice)\n* [Debugging](#debugging)\n*   *   [Valgrind](#valgrind)\n* [GTK](#gtk)\n    *   [Installing GTK](#installing-gtk)\n    *   [Compiling GTK](#compiling-gtk)\n    *   [Learning GTK](#learning-gtk)\n* [Miscellaneous](#miscellaneous)\n    *   [Math `pow()` function](#math-pow-function)\n    *   [`printf` function outputs unwanted characters](#printf-function-outputs-unwanted-characters)\n    *   [Interesting stuff to do](#interesting-stuff-to-do)\n    *   [I C what you did there](#i-c-what-you-did-there)\n\n* * *\n\n### Character Conversion\n\n#### Leading blank for `scanf()`\n\nFrom [this post](https://stackoverflow.com/questions/5240789/scanf-leaves-the-newline-character-in-the-buffer) on StackOverflow :\n\n*Use `\" %c\"` with a leading blank to skip optional white space. Do not use a trailing blank in a `scanf()` format string.*\n\nWithout doing this, `scanf()` was not actually waiting for user input\nbut taking the **LF** as input (Printing out the variable showed ASCII char '10', Line Feed).\n\n```\n    char ascii_char;\n    printf(\"Please enter a char: \");\n    scanf(\" %c\", \u0026ascii_char); --\u003e HERE\n    printf(\"%i\\n\", ascii_char);\n```\n\n### Operators\n\n#### Ternary operators\n\nIt's always nice to use ternary operators. They look like this :\n\n```\nbool isEven = ((number % 2) == 0) ? true : false;\n```\n\n#### Unary operators\n\nIn the example below :\n\n```\n    int pizzas_to_eat = 100;\n    int output = pizzas_to_eat++;\n```\n\nThe value of `output` is set to **100** :pushpin: :heavy_exclamation_mark: :100: :warning:\n\nThe unary operator `++` increases the value of `pizzas_to_eat` only after it's value\nwas assigned to `output`.\n\nTo increment the value of `pizzas_to_eat` **BEFORE** assigning it's value to `output`,\nthe operator needs to be placed before the variable :\n\n```\n    int pizzas_to_eat = 100;\n    int output = ++pizzas_to_eat;\n```\n\nHere the value of `output` will be **101** :heavy_exclamation_mark:\n\n### Pointers\n\n#### \"Address of\" and \"value of\" operators\n\nAlways good to have a reminder of this : \n\n```\nint a = 100;\n\n*ptr = \u0026a;\n\n```\n\nSecond line : **declaring a pointer to an integer and initializing it with address of a.**\n\n#### Pointers to struct fields\n\nFrom [OverIQ](https://overiq.com/c-programming-101/pointer-to-a-structure-in-c/) :\n\n* * *\nThere are two ways of accessing members of structure using pointer:\n\n    - Using indirection (*) operator and dot (.) operator.\n    - Using arrow (-\u003e) operator or membership operator.\n* * *\n\nThis means :\n\n`(*person).age` (here `person` holds the struct itself)\n\nis equivalent to :\n\n`person-\u003eage` (here `person` holds the address of the struct)\n\n#### Initializing arrays of integers\n\nWhen I wrote a function to multiply two vectors, I did something such as :\n\n```\nconst int array_size = 3;\nint vector[array_size] = {1, 2, 3};\n```\n\nAnd would see the error below :\n\n```\nerror: switch jumps into scope of identifier with variably modified type\n\nnote: switch starts here\n    switch(menu_option) {\n    ^\nnote: v1 declared here\n    int v1[length];\n    ^\n```\n\nBecause the assignment was found in one case of a switch statement,\nthe error would be thrown with a mention of it. But as explained in\n[this answer](https://stackoverflow.com/a/3082986), C does not allow it :\n\n*You receive this error because in C language you are\nnot allowed to use initializers with variable length arrays.*\n\nAn easy solution to this is to set the size as a constant and use\nthat constant :\n\n```\nìnt vector[ARRAY_LEN];\n```\n\n### Threads and Procs\n\n#### Why does a printf after `fork()` display twice?\n\nSo here you are, just chilling, and occasionally doing a call to `fork()`,\nand of course being careful you want to make sure it worked, BUT THEN ...\n\n```\n    int pid = fork();\n    if (pid == -1)\n    {\n        perror(\"OH NO ! :(\");\n    } else {\n        printf(\"OH YEAH ! :)\\n\");\n    }\n```\n\nOutputs :\n\n```\nOH YEAH ! :)\nOH YEAH ! :)\n```\n\nSo at first, my face was like : \" :thinking: :thinking: :thinking: \" ...\n\nBut then I read [this](https://www.geeksforgeeks.org/fork-system-call/) ! Duh !\nHad I read some docs earlier or remembered my C course from uni\nthis would have been obvious ! \n\n**AFTER THE LINE WHERE `fork()` IS CALLED, THE SAME CODE IS EXECUTED BY BOTH CHILD AND PARENT PROC !**\n\nInstead of printing as described above, the alternative below is preferred :\n\n```\n    if (pid == 0)\n    {\n        printf(\"Hi I am the kid\\n\"); // pid = 0 is returned to child proc\n    } else {\n        printf(\"Hi I am the papa\\n\"); // pid \u003e 0 is returned to parent proc\n    }\n```\n\nWhat it looks like with 3 consecutive calls to `fork()` (8 procs in total since 2³ = ) :\n\nSource : [`fork()` in C](https://www.geeksforgeeks.org/fork-system-call/) from GeeksforGeeks.\n\n```\nfork ();   // Line 1\nfork ();   // Line 2\nfork ();   // Line 3\n\n       L1       // There will be 1 child process \n    /     \\     // created by line 1.\n  L2      L2    // There will be 2 child processes\n /  \\    /  \\   //  created by line 2\nL3  L3  L3  L3  // There will be 4 child processes \n                // created by line 3\n\n```\n\nSo there are total eight processes (new child processes and one original process).\n\nIf we want to represent the relationship between the processes as a tree hierarchy it would be the following:\n\n- The main process: P0\n- Processes created by the 1st fork: P1\n- Processes created by the 2nd fork: P2, P3\n- Processes created by the 3rd fork: P4, P5, P6, P7\n\n```\n            P0        \n         /  |   \\     \n       P1   P4   P2   \n      /  \\         \\  \n    P3    P6        P5\n   /                  \n P7\n```\n### Debugging\n\n#### Valgrind\nHow to track memory leaks using Valgrind :\n\n```\nvalgrind --leak-check=yes --track-origins=yes -s ./program\n```\n\nAnd the most satisfying output you can possibly imagine having from that is\nsomething that looks like :\n\n```\n==41563== HEAP SUMMARY:\n==41563==     in use at exit: 0 bytes in 0 blocks\n==41563==   total heap usage: 5 allocs, 5 frees, 2,880 bytes allocated\n==41563== \n==41563== All heap blocks were freed -- no leaks are possible\n==41563== \n==41563== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)\n```\n\n**Never forget to free !**\n\n### GTK\n\n#### Installing GTK\n\nTo install GTK version 4 (latest at time of writing) :\n\n```\nsudo apt install libgtk-4-dev\n```\n\nto install version 3 (more stable ?) :\n\n```\nsudo apt install libgtk-3-dev\n```\n\n#### Compiling GTK\n\nFor some reason the exact same command works in terminal but produces an\nerror using make.\n\nCompiling with output :\n\n```\ngcc $( pkg-config --cflags gtk4 ) -o gui gui.c $( pkg-config --libs gtk4 )\n```\n\n**NOTE** : having a `main` function is mandatory, otherwise the linker will fail.  \n\n#### Learning GTK\n\nSome pretty cool references I found :\n\n* [GTK Tutorial](https://github.com/ToshioCP/Gtk4-tutorial)\n* [GTK Drag n Drop](https://github.com/aeldemery/gtk4_dnd)\n\n### Miscellaneous\n\n#### Math `pow()` function\n\nTrying to use the `math.h` function `pow()`, \nI ran into the error described [in this post](https://stackoverflow.com/questions/12824134/undefined-reference-to-pow-in-c-despite-including-math-h).\n\nFor some reason even with the linker flag, I kept getting the same error\nso I just wrote a power function :smile:\n\n#### `printf` function outputs unwanted characters\n\nSometimes you just need to print out things to console to see what you're doing.\nBut sometimes you also end up with random gibberish characters on top of your output.\n\nFor example :\n\n![What the heck is this?](https://imgur.com/522jQC6.png)\n\nFortunately, some smart people helped me figure out why such event may come to occur.\nQuoting a reply on [this post](https://stackoverflow.com/a/49693582) : \n\n*Therefore, if the last character in your array isn't 0, the above loop will continue until there happens to be a 0 somewhere in the memory that follows.*\n\nSince the `bit_wisdom` function was returning an array of characters without a terminating zero,\ncalling `printf` on the result with a string conversion character (`%s`) would loop through the array,\nprint the whole thing and then keep printing characters because `'\\0'` was never used.\n\nSo instead of returning an array of 32 characters, I changed `bit_wisdom` to return\nan array of 33 characters, all set to `'\\0'` using `memset` at the beginning and of which\nthe first 32 would be filled with the binary representation of the number.\n\nThe result is a clean print : :smile: \n\n![What the heck is this?](https://imgur.com/MhR9J2F.png)\n\n#### Interesting stuff to do\n\n* Bitwise calculus\n* Protocols (HTTP, FTP, etc.)\n* Vector/Matrix calculus\n* Kernel modules\n* Something with AI in C\n\n#### I C what you did there\n![Smol kotik](https://media.giphy.com/media/vFKqnCdLPNOKc/giphy.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaymer%2Fupgraded-potato","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaymer%2Fupgraded-potato","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaymer%2Fupgraded-potato/lists"}