{"id":18343726,"url":"https://github.com/nunorc/c-lang-notes","last_synced_at":"2025-04-09T21:54:49.662Z","repository":{"id":137587128,"uuid":"84187813","full_name":"nunorc/c-lang-notes","owner":"nunorc","description":"C programming language notes","archived":false,"fork":false,"pushed_at":"2017-03-07T17:50:59.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T21:54:46.679Z","etag":null,"topics":["c"],"latest_commit_sha":null,"homepage":null,"language":null,"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/nunorc.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":"2017-03-07T10:45:15.000Z","updated_at":"2017-03-09T21:21:26.000Z","dependencies_parsed_at":"2023-03-14T23:45:58.862Z","dependency_job_id":null,"html_url":"https://github.com/nunorc/c-lang-notes","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/nunorc%2Fc-lang-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nunorc%2Fc-lang-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nunorc%2Fc-lang-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nunorc%2Fc-lang-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nunorc","download_url":"https://codeload.github.com/nunorc/c-lang-notes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248119398,"owners_count":21050754,"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"],"created_at":"2024-11-05T20:41:28.622Z","updated_at":"2025-04-09T21:54:49.645Z","avatar_url":"https://github.com/nunorc.png","language":null,"readme":"\n# C Programming Language Notes\n\nSome notes on the C programming language. To compile and run a C program using\n`gcc`:\n\n```bash\n$ gcc hello.c -o hello\n$ ./hello\nHello, World!\n```\n\n## Variables and Types\n\nVariables and constants are the basic data objects that can be used\nin a program. These are referenced by name, these names are made up of\nletters and digits, but the first character of the name need to be\na letter (the underscore `_` counts as a letter).\n\n### Declarations\n\nAll variables must be declared before use. A declaration specifies a\ntype and a list of one or more variables of that type, for example:\n```C\nint i;\nchar c;\n```\nor, using a list of variables\n```C\nint max, min, step;\n```\nVariables can be initialized in the declaration, for example:\n```C\nint max = 10, min = 0, step = 2;\n```\n\n### Basic Data Types\n\nThere are four basic data types:\n\n* `int` for integer numbers, for example `int i = 0;`.\n* `char` for single characters, for example `char c = 'a';`.\n* `float` for single-precision floating point, for example `float f = 3.14;`.\n* `double` for double-precision floating point, for example `double d = 9e+12;`.\n\nThe following modifiers can be applied to these basic types: `short`, `long`, \n`signed`, and `unsigned`.\n\n### Constants\n\nConstants are fixed values that do not change during program\nexecution. This prevents unintended changing their values.\n\nThere are two ways of defining constants:\n\n* `#define` use the preprocessor to define a constants.\n* `const` using the reserved keyword to declare a constant variable.\n\nExamples of the first option are:\n```C\n#define MAX  1000\n#define NEWLINE '\\n'\n```\nWhere the `#define` keyword is followed by the name of the constant, and\nthe value, i.e.:\n```\n#define \u003cname\u003e \u003cvalue\u003e\n```\nDuring the preprocessor run, all the instances of the constant in the\nprogram are replaced by the value.\n\nThe second option is prefixing a variable declaration with the `const`\nkeyword:\n```C\nconst int length = 10;\n```\n\n## Operators \n\nThe binary (use two operands) arithmetic operators are:\n\n* `+` for summing values.\n* `-` for subtracting.\n* `*` for multiplication.\n* `/` for division.\n* `%` for the remainder of integer division.\n\nThe relational operators used to compare values are:\n\n* `\u003e` to test for greater then.\n* `\u003e=` for greater or equal than.\n* `\u003c`  for less than.\n* `\u003c=` for less or equal than.\n* `==` for equality.\n* `!=` for not equal.\n\nLogical operators:\n\n* `\u0026\u0026`\n* `||`\n\nWhen operators have different types, they are converted to a common type\n(this is not always possible). In general the only automatic conversions are those\nfrom a \"narrower\" operand into a \"wider\" operand without loosing information\n(for example, from integer to float).\n\nType casting can be used to force a conversion of a value, by including the intended\ntype between parentheses. For example:\n\n```C\nint sum = 17, count = 5;\ndouble mean;\nmean = (double) sum / count;\n```\n\n## Arrays\n\nAn array is a structure to store a sequential, fixed size, collection of\nelements of the same type. Arrays indexes in C start a 0. The generic\nway of declaring arrays is:\n```\n\u003ctype\u003e \u003cname\u003e[\u003csize\u003e];\n```\nFor example, declare an array of integers of size 10 (the index of this\narray goes from 0 to 9):\n```C\nint array[10];\n```\nArrays can also be initialized in the declaration, for example to initialize\nthe previous example with the numbers from 1 to 10::\n```C\nint array[10] = {1,2,3,4,5,6,7,8,9,10};\n```\nTo access the values of an array declare an expression with the array name,\nand the index of the intended value, for example to add the first two\nelements of the previous array:\n```C\nadd = array[0] + array[1];\n```\nTo scroll through an list of elements of an array of size `N` a loop can\nbe used, the following `for` loop iterates over all the elements of the\narray, starting at index 0, and finishing at index `N-1`\n```C\nfor (i = 0; i \u003c N; i++) {\n   (...)\n}\n```\n\n### Strings\n\nStrings are a specific example of a one-dimension array. Where each element\nin the data collection is a single character. One important detail, the\nlast element in a string is *always* the literal `\\0`. An example of\ndeclaring and initializing a new string following the previous array\nexamples is:\n```C\nchar str[] = {'H', 'e', 'l', 'l', 'o', '\\0'};\n```\nThe following shortcut can be used to achieve the same declaration:\n```C\nchar str[] = \"Hello\";\n```\nNote that in the second option there is no need to explicitly add the\ntrailing `'\\0'` literal. Strings can be transversed and handled like\nany other array.\n\n## Functions\n\nFunctions are used to organize a set of statements that execute a specific\ntask. This isolates specific parts of the program, allowing to write code\nthat is easier to read, understand and maintain.\n\nThe generic way for defining a function is:\n```\n\u003creturn_type\u003e \u003cname\u003e(\u003cargument_list\u003e) {\n  \u003cbody\u003e\n}\n```\nFor example to declare a function named `add` that has two arguments (two)\nnumbers, and returns the numbers addition:\n```C\nint add(int x, int y) {\n  return x+y;\n}\n```\nThe `return` keyword is used to return the intended value and control flow\nback to the function caller.\nTo call a function, use the function name, and use parentheses to declare the\narguments list. For example to call the `add` function example to sum the\nnumbers `3` and `5`:\n```C\nsum = add(3, 5);\n```\nAll function argument are passed to functions\nby value for default, this means that you can change the value of the argument\ninside a function without changing the original variable from which was called.\nArrays and strings are always passed by reference by default, this means that\nif you change an array inside a function the original array will also be\nchange, because they point to the same data.\n\nFunctions must be declared before used, a function prototype (just the function\nsignature) can be made explicitly before describing the function body. For example,\nthe function prototype for the `add` function is:\n```C\nint add(int x, int y);\n```\n\n## *Structs*\n\nStructures are used in C to organize together a collection of variables so\nit can be treated as an unit. For example to represent a point in 2D space\nthe following *struct* can be used:\n\n```C\nstruct point {\n  int x;\n  int y;\n};\n```\n\nWhere `point` is the tag name for the declared *struct* that contains two\nvariables of type `int`: `x` and `y`. Variables inside a *struct*\nare usually called members. This declaration defines a new type:\n`struct point` which can be used to declare new variables as any other\ntype. For example to declare two new variables `p1` and `p2` of this type:\n```C\nstruct point p1, p2;\n```\nThese variables can also be initialized in the declaration:\n```C\nstruct point p = { 10, 20 };\n```\nThis declares a new point `p` where `x` is initialized with the value `10`,\nand `y` with the value `20`.\n\nIndividual members of the *struct* can be accessed with the `.` (single dot)\noperator. For example to print the values of the previous example:\n```C\nprintf(\"%d, %d\", p.x, p.y);    // prints: 10, 20\n```\nOr to update the values:\n```C\np.x = 30;\np.y = 40;\n```\n\nStructures can be nested, for example a rectangle can be defined using two\npoints:\n```C\nstruct rectangle {\n    struct point p1;\n    struct point p2;\n};\n```\nThe `.` operator is used to update or retrieved values in the the nested structure:\n```C\nstruct rectangle r;\nr.p1.x = 10;\nr.p1.y = 20;\nprintf(\"%d, %d\", r.p1.x, r.p1.y);\n```\n\nStructures, as any other variable type, can be returned from functions, or handled\nas arguments. For example to define a function that creates and returns a new\npoint given its' x an y coordinate:\n```C\nstruct point new(int x, int y) {\n    struct point n;\n    n.x = x;\n    n.y = y;\n    return n;\n}\n```\n\n## *typedef*\n\n`typedef` is used in C to give new names to types. For example the\ndeclaration\n```C\ntypedef int Length;\n```\ncreates a new alias (`Length`) for the type `int`. This new alias can\nbe used exactly as any other type. For example to declare a new variable:\n```C\nLength l = 10;\n```\n\nThis approach can also be used to give name types to user defined *structs*.\nFor example to give a new name (`POINT`) to the example *struct* defined\nin the previous section:\n```C\ntypedef struct point {\n  int x,\n  int y,\n} POINT;\n```\nNow instead of having to use `struct point`, we can use `POINT` as a type.\nFor example in the function prototype `new` that returns a new point:\n```C\nPOINT new(int x, int y);\n```\n\n\n## Pointers\n\nA pointer is a variable that stores the address of another variable.\nFor example, the following declaration creates a new variable `i` of\ntype `int` with the value `10`:\n```C\nint i = 10;\n```\nTo declare a new variable that is a pointer to an `int` an `*` is added,\nfor example declare a new pointer `p`:\n```C\nint *p;\n```\nTo assign this new pointer to \"point to\" the `i` variable declared previously\nthe `\u0026` operator is used, which tells us the address where the variable\nis stored.\n```C\np = \u0026i;\n```\nNow `i` continues to be a variable, and `p` is another variable (a pointer)\nthat points to `i`. To get the value pointed by `p` use the `*`, this is\nusually call dereferencing:\n```C\nprintf(\"%d\", i);   // prints 10\nprintf(\"%d\", *p);  // prints 10\n```\n\nPointers can be passed as function arguments, for example given the\nfollowing prototype for the `swap`function:\n```C\nvoid swap(int x, int y);\n```\nThe goal of this function is to swap the value of two variables, the\nproblem is that in this case the values for `x` and `y` are being passed\nby value, which means that even they are swapped inside the function,\nthe variables from where the function were called will remain the same.\nBut, we can change the function to receive two pointers as arguments:\n```C\nvoid swap(int *px, int *py);\n```\nNow we are passing the arguments by reference, meaning that what we\nare use inside the function are not a copy of the values from the caller,\nbut a reference to the values themselves (references), meaning that if\nthe values are swapped inside the function, they will remain swapper\nwhen the function returns to the caller. Remember that now we need to\npass the pointers when calling the function:\n```C\nint a = 10, b = 20;\nswap(\u0026a, \u0026b);\nprintf(\"%d, %d\", a, b);  // prints: 20, 10\n```\n\nArray subscripting can also be achieved using pointers. For example,\ndeclaring a array `a` of `10` elements of type `ìnt`:\n```C\nint a[10];\n```\nBasically this is a block of ten consecutive objects of type `int`. If we\ndeclare `pa` as a pointer to an integer:\n```C\nint *pa;\n```\nAfter the following assignment:\n```C\npa = \u0026a[0];\n```\nthe pointer is \"pointing at\" the first element of the array `a`. For example\nto print the first element of the arrawy pointed by `pa` we can use:\n```C\nprintf(\"%d\", *pa);\n```\nWe are using the `*` to *dereference* the pointer which gives us the value\npointed\nat, i.e. the value stored in the first element of the array. So, if `pa` points\nto the first element of the array, `pa+1` points to the second, `pa+2` points\nto the third, more generically `pa+i` points to `i` elements after the element\n`pa` is pointing at. This is true regardless of the type of variable. For example\nthe following `for` loop counts the length of a string pointer `s`:\n```C\nfor (count = 0; *s != '\\0'; s++)\n  count++;\n```\nBecause a string is an array of characters and `s` is of type `char *` (a pointer),\nthe `*s` is used to get the character element in the position we are, and `s`\n(the pointer) is incremented by 1 in each iteration, i.e. point to the next element\nof the array (the next character of the string).\n\n## Files\n\nTo read or write from a file, the first step is to open the file. To do this\nfirst we declare new pointer of type `FILE` (types and functions\ndescribed here are provided by the `stdio.h`):\n```C\nFILE *fp;\n```\nAnd the open the file using the `fopen` function:\n```C\nfp = fopen(\"input.dat\", \"r\");\n```\nthe first argument to the `fopen` function is a string with the name of the\nfile to open, and the second argument is also a string defining the\n*mode*: read (\"r\"), write (\"w\"), or append (\"a\"). After the file is used,\nthe `fclose` function is used to close the connection to the file.\n```C\nfclose(fp);\n```\nThe `fread` and `fwrite` functions, are used to read and write binary data\nfrom and to files. For example to write the `point` *struct* defined in a\nprevious section to the file opened in `fp`:\n```C\nfwrite(\u0026p1, sizeof(struct point), 1, fp);\n```\nThe first argument is a pointer to the variable, so in this example the\n`\u0026` is required to get the memory address of the variable; the second\nargument is the size of the *struct* that is computed using the `sizeof`\nfunction; the third argument is the number of elements to write; and\nthe last argument is the file pointer. To read back the data from file,\nand store it back in memory using the `fread` function:\n```C\nfread(\u0026p1, sizeof(struct point), 1, fp);\n```\n\nIn particular single characters can be read from a file pointer using\nthe `getc` function, and written using the `putc` functions:\n```C\nc = getc(fp);\nputc(c, fp);\n```\nAnd complete strings using the `fscanf` and `fprintf` functions, which\nbehave as their `scanf` and `printf` counterparts but take an additional\nargument: the file pointer to scan from or print, for example:\n```C\nfscanf(fp, \"%s\", str);\nfprintf(fp, \"%s\", str);\n```\nFull lines of input can be read from a file using the `fgets` function,\nand written using the `fputs` function, for example:\n```C\nfgets(line, MAX, fp);\nfputs(line, fp);\n```\nBoth functions take as one argument the character array pointer where to\nset/get the line and the file pointer. `fgets` takes an extra argument:\nthe maximum number of characters that it will read.\n\n# References\n\n  * Brian W. Kernighan, and Dennis M. Ritchie. The C Programming Language\n(2nd ed.). Prentice Hall. 1988.\n\n# Disclaimer\n\nThis document is just a collection of notes, topics coverage is **not** complete, and\nmany details were omitted on purpose if favor of simplicity. For complete\ndetails on the C programming language read the references.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnunorc%2Fc-lang-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnunorc%2Fc-lang-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnunorc%2Fc-lang-notes/lists"}