Update
This commit is contained in:
parent
a508d177e9
commit
2eb10d9bba
15 changed files with 1821 additions and 1703 deletions
148
c.md
148
c.md
|
@ -22,11 +22,9 @@ Mainstream consensus acknowledges that C is among the best languages for writing
|
|||
|
||||
## History and Context
|
||||
|
||||
C was developed in 1972 at [Bell Labs](bell_labs.md) alongside the [Unix](unix.md) operating system by [Dennis Ritchie](dennis_ritchie.md) and [Brian Kerninghan](brian_kerninghan.md), as a successor to the [B](b.md) language ([portable](portability.md) language with [recursion](recursion.md)) written by Denis Ritchie and [Ken Thompson](ken_thompson.md), which was in turn inspired by the the [ALGOL](algol.md) language (code blocks, lexical [scope](scope.md), ...).
|
||||
C was developed in 1972 at [Bell Labs](bell_labs.md) alongside the [Unix](unix.md) operating system by [Dennis Ritchie](dennis_ritchie.md) and [Brian Kerninghan](brian_kerninghan.md), as a successor to the [B](b.md) language ([portable](portability.md) language with [recursion](recursion.md)) written by Denis Ritchie and [Ken Thompson](ken_thompson.md), which was in turn inspired by the the [ALGOL](algol.md) language (code blocks, lexical [scope](scope.md), ...). C was for a while called NB for "new B".
|
||||
|
||||
In 1973 Unix was rewritten in C. In 1978 Keninghan and Ritchie published a book called *The C Programming Language*, known as *K&R*, which became something akin the C specification. In 1989, the [ANSI C](ansi_c.md) standard, also known as C89, was released by the American ANSI. The same standard was also adopted a year later by the international ISO, so C90 refers to the same language. In 1999 ISO issues a new standard that's known as C99.
|
||||
|
||||
TODO
|
||||
In 1973 Unix was rewritten in C. In 1978 Keninghan and Ritchie published a book called *The C Programming Language*, known as *K&R*, which became something akin the C specification. In 1989, the [ANSI C](ansi_c.md) standard, also known as C89, was released by the American ANSI -- this is a very well supported and overall good standard. The same standard was also adopted a year later by the international ISO, so C90 refers to the same language. In 1999 ISO issues a new standard that's known as C99, still a very good standard embraced by [LRS](lrs.md). Later in 2011 and 2017 the standard was revised again to C11 and C17, which are however no longer considered good.
|
||||
|
||||
## Standards
|
||||
|
||||
|
@ -48,12 +46,20 @@ The standards of C99 and older are considered pretty [future-proof](future_proof
|
|||
|
||||
## Compilers
|
||||
|
||||
C is extreme well established, standardized and implemented so there is a great number of C compilers around. Let us list only some of the more notable ones.
|
||||
|
||||
- [gcc](gcc.md): The main "big name" that can compile all kinds of languages including C, used by default in many places, very [bloated](bloat.md) and can take long to compile big programs, but is pretty good at [optimizing](optimization.md) the code and generating fast code. Also has number of frontends and can compile for many platforms. Uses GENERIC/GIMPLE [intermediate representation](intermediate_representation.md).
|
||||
- [clang](clang.md): Another big bloated compiler, kind of competes with gcc, is similarly good at optimization etc. Uses [LLVM](llvm.md) intermediate representation.
|
||||
- [tcc](tcc.md): Tiny C compiler, [suckless](suckless.md), orders of magnitude smaller (currently around 25 KLOC) and simpler than gcc and clang, cannot optimize nearly as well as the big compilers so the generated executables can be a bit slower and bigger, however besides its internal simplicity there are many advantages, mainly e.g. fast compilation (claims to be 9 times faster than gcc) and small tcc executable (about 100 kB). Seems to only support x86.
|
||||
- [scc](scc.md): Another small/suckless C compiler, currently about 30 KLOC.
|
||||
- [DuskCC](duskcc.md): [Dusk OS](duskos.md) C compiler written in [Forth](forth.md), focused on extreme simplicity, probably won't adhere to standards completely.
|
||||
- [8c](8c.md), [8cc](8cc.md)
|
||||
- [8c](8c.md), [8cc](8cc.md), [chibicc](chibicc.md): Some other small compilers.
|
||||
- [c2bf](c2bf.md): Partially implemented C to [brainfuck](brainfuck.md) compiler.
|
||||
- [lcc](lcc.md): Proprietary, source available small C compiler, about 20 KLOC.
|
||||
- [pcc](pcc.md): A very early C compiler that was later developed further to support even the C99 standard.
|
||||
- Borland Turbo C: old proprietary compiler with [IDE](ide.md).
|
||||
- [sdcc](sdcc.md) (small device C compiler): For small 8 bit [microcontrollers](mcu.md).
|
||||
- msvc ([Micro$oft](microsoft.md) visual C++): Badly bloated proprietary C/C++ compiler by a shitty corporation. Avoid.
|
||||
- ...
|
||||
|
||||
## Standard Library
|
||||
|
@ -94,8 +100,8 @@ A simple program in C that writes "welcome to C" looks like this:
|
|||
|
||||
int main(void)
|
||||
{
|
||||
// this is the main program
|
||||
|
||||
// this is the main program
|
||||
|
||||
puts("welcome to C");
|
||||
|
||||
return 0; // end with success
|
||||
|
@ -108,26 +114,52 @@ You can simply paste this code into a file which you name e.g. `program.c`, then
|
|||
|
||||
Then if you run the program from command line (`./program` on Unix like systems) you should see the message.
|
||||
|
||||
## Cheatsheet
|
||||
## Cheatsheet/Overview
|
||||
|
||||
It's pretty important you learn C, so here's a little cheat sheet for you.
|
||||
Here is a quick reference cheatsheet of some of the important things in C, also a possible overview of the language.
|
||||
|
||||
**data types** (just some):
|
||||
|
||||
- **int**: signed integer, at least 16 bits (-32767 to 32767) but usually more
|
||||
- **unsigned int**: unsigned integer, at least 16 bit (0 to 65535) but usually more
|
||||
- **char**: smallest integer of at least 8 bits (1 byte, 256 values), besides others used for containing [ASCII](ascii.md) characters
|
||||
- **unsigned char**: like char but unsigned (0 to 255)
|
||||
- **float**: [floating point](float.md) number (usually 32 bit)
|
||||
- **double**: like float but higher precision (usually 64 bit)
|
||||
- **short**: smaller signed integer, at least 16 bits (−32767 to 32767)
|
||||
- **long**: bigger signed integer, at least 32 bits (-2147483647 to 2147483647)
|
||||
- **pointer**: memory address (size depends on platform), always tied to a specific type, e.g. a pointer to integer: `*int`, pointer to double: `*double` etc.
|
||||
- **array**: a sequence of values of some type, e.g. an array of 10 integers: `int[10]`
|
||||
- **struct**: structure of values of different types, e.g. `struct myStruct { int myInt; chat myChar; }`
|
||||
- note: header *stdint.h* contains fixed-width data types such as *uint32_t* etc.
|
||||
- note: there is no **string**, a string is an array of *char*s which must end with a value 0 (string terminator)
|
||||
- note: there is no real **bool** (actually it is in header *stdbool*), integers are used instead (0 = false, 1 = true)
|
||||
| data type | values (size) | printf |notes |
|
||||
| ------------------------- | ------------------------------------------------------ | ---------- | -------------------------------------------------- |
|
||||
| `int` (`signed int`, ...) | integer, at least -32767 to 32767 (16 bit), often more | `%d` | native integer, **fast** (prefer for speed) |
|
||||
| `unsigned int` | integer, non-negative, at least 0 to 65535, often more | `%u` | same as `int` but no negative values |
|
||||
| `signed char` | integer, at least -127 to 127, mostly -128 to 127 |`%c`, `%hhi`| `char` forced to be signed |
|
||||
| `unsigned char` | integer, at least 0 to 255 (almost always the case) |`%c`, `%hhu`| smallest memory chunk, **[byte](byte.md)** |
|
||||
| `char` | integer, at least 256 values | `%c` | signed or unsigned, used for string characters |
|
||||
| `short` | integer, at least -32767 to 32767 (16 bit) | `%hd` | like `int` but supposed to be smaller |
|
||||
| `unsigned short` | integer, non-negative, at least 0 to 65535 | `%hu` | like `short` but unsigned |
|
||||
| `long` | integer, at least -2147483647 to 2147483647 (32 bit) | `%ld` | for big signed values |
|
||||
| `unsigned long` | integer, at least 0 to 4294967295 (32 bit) | `%lu` | for big unsigned values |
|
||||
| `long long` | integer, at least some -9 * 10^18 to 9 * 10^18 (64 bit)| `%lld` | for very big signed values |
|
||||
| `unsigned long long` | integer, at least 0 to 18446744073709551615 (64 bit) | `%llu` | for very big unsigned values |
|
||||
| `float` | floating point, some -3 * 10^38 to 3 * 10^38 | `%f` |[float](float.md), tricky, bloat, can be slow, avoid|
|
||||
| `double` | floating point, some -1 * 10^308 to 10^308 | `%lf` | like `float` but bigger |
|
||||
| `T [N]` | array of `N` values of type `T` | | **array**, if `T` is `char` then **string** |
|
||||
| `T *` | memory address | `%p` | pointer to type `T`, (if `char` then **string**) |
|
||||
| `uint8_t` | 0 to 255 (8 bit) |`PRIu8` |exact width, two's compl., must include `<stdint.h>`|
|
||||
| `int8_t` | -128 to 127 (8 bit) |`PRId8` | like `uint8_t` but signed |
|
||||
| `uint16_t` | 0 to 65535 (16 bit) |`PRIu16` | like `uint8_t` but 16 bit |
|
||||
| `int16_t` | -32768 to 32767 (16 bit) |`PRId16` | like `uint16_t` but signed |
|
||||
| `uint32_t` | -2147483648 to 2147483647 (32 bit) |`PRIu32` | like `uint8_t` but 32 bit |
|
||||
| `int32_t` | 0 to 4294967295 (32 bit) |`PRId32` | like `uint32_t` but signed |
|
||||
| `int_least8_t` | at least -128 to 127 |`PRIdLEAST8`| signed integer with at least 8 bits, `<stdint.h>` |
|
||||
| `int_fast8_t` | at least -128 to 127 |`PRIdFAST8` | fast signed int. with at least 8 bits, `<stdint.h>`|
|
||||
| struct | | | structured data type |
|
||||
|
||||
There is no **bool** (true, false), use any integer type, 0 is false, everything else is true (there may be some bool type in the stdlib, don't use that). A **string** is just array of chars, it has to end with value 0 (NOT ASCII character for "0" but literally integer value 0)!
|
||||
|
||||
**main program structure**:
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// code here
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**branching aka if-then-else**:
|
||||
|
||||
|
@ -160,7 +192,7 @@ while (CONDITION)
|
|||
}
|
||||
```
|
||||
|
||||
**do while loop** (same as *while* but CONDITION at the end):
|
||||
**do while loop** (same as *while* but CONDITION at the end), not used that much:
|
||||
|
||||
```
|
||||
do
|
||||
|
@ -176,8 +208,74 @@ RETURN_TYPE myFunction (TYPE1 param1, TYPE2 param2, ...)
|
|||
{ // return type can be void
|
||||
// do something here
|
||||
}
|
||||
|
||||
```
|
||||
**compilation** (you can replace `gcc` with another compiler):
|
||||
|
||||
- quickly compile and run: `gcc myprogram.c && ./a.out`.
|
||||
- compile more properly: `gcc -std=c99 -Wall -Wextra -pedantic -O3 -o myprogram myprogram.c`.
|
||||
|
||||
To **[link](linking.md)** a library use `-llibrary`, e.g. `-lm` (when using `<math.h>`), `-lSDL2` etc.
|
||||
|
||||
The following are some symbols ([functions](function.md), [macros](macro.md), ...) from the **standard library**:
|
||||
|
||||
| symbol | library | description | example |
|
||||
| ------------------------- | --------------- | ------------------------------------------------------------------ | ---------------------------------------- |
|
||||
| *putchar(c)* | *stdio.h* | Writes a single character to output. | `putchar('a');` |
|
||||
| *getchar()* | *stdio.h* | Reads a single character from input. | `int inputChar = getchar();` |
|
||||
| *puts(s)* | *stdio.h* | Writes string to output (adds newline at the end). | `puts("hello");` |
|
||||
| *printf(s, a, b, ...)* | *stdio.h* | Complex print func., allow printing numbers, their formatting etc. | `printf("value is %d\n",var);` |
|
||||
| *scanf(s, a, b, ...)* | *stdio.h* | Complex reading func., allows reading numbers etc. | `scanf("%d",&var);` |
|
||||
| *fopen(f,mode)* | *stdio.h* | Opens file with given name in specific mode, returns pointer. | `FILE *myFile = fopen("myfile.txt","r");`|
|
||||
| *fclose(f)* | *stdio.h* | Closes previously opened file. | `fclose(myFile);` |
|
||||
| *fputc(c,f)* | *stdio.h* | Writes a single character to file. | `fputc('a',myFile);` |
|
||||
| *fgetc(f)* | *stdio.h* | Reads a single character from file. | `int fileChar = fgetc(myFile);` |
|
||||
| *fputs(s,f)* | *stdio.h* | Writes string to file (without newline at end). | `fputs("hello",myFile);` |
|
||||
| *fprintf(s, a, b, ...)* | *stdio.h* | Like `printf` but outputs to a file. | `fprintf(myFile,"value is %d\n",var);` |
|
||||
| *fscanf(f, s, a, b, ...)* | *stdio.h* | Like `scanf` but reads from a file. | `fscanf(myFile,"%d",&var);` |
|
||||
| *fread(data,size,n,f)* | *stdio.h* | Reads *n* elems to *data* from *file*, returns no. of elems read. | `fread(myArray,sizeof(item),1,myFile);` |
|
||||
| *fwrite(data,size,n,f)* | *stdio.h* | Writes *n* elems from *data* to *file*, returns no. of elems writ. | `fwrite(myArray,sizeof(item),1,myFile);` |
|
||||
| *EOF* | *stdio.h* | [End of file](eof.md) value. | `int c = getchar(); if (c == EOF) break;`|
|
||||
| *rand()* | *stdlib.h* | Returns pseudorandom number. | `char randomLetter = 'a' + rand() % 26;` |
|
||||
| *srand(n)* | *stdlib.h* | Seeds pseudorandom number generator. | `srand(time(NULL));` |
|
||||
| *NULL* | *stdlib.h*, ... | Value assigned to pointers that point "nowhere". | `int *myPointer = NULL;` |
|
||||
| *malloc(size)* | *stdlib.h* | Dynamically allocates memory, returns pointer to it (or NULL). | `int *myArr = malloc(sizeof(int) * 10);` |
|
||||
| *realloc(mem,size)* | *stdlib.h* | Resizes dynamically allocates memory, returns pointer (or NULL). |`myArr = realloc(myArr,sizeof(int) * 20);`|
|
||||
| *free(mem)* | *stdlib.h* | Frees dynamically allocated memory. | `free(myArr);` |
|
||||
| *atof(str)* | *stdlib.h* | Converts string to floating point number. | `double val = atof(answerStr);` |
|
||||
| *atoi(str)* | *stdlib.h* | Converts string to integer number. | `int val = atof(answerStr);` |
|
||||
| *EXIT_SUCCESS* | *stdlib.h* | Value the program should return on successful exit. | `return EXIT_SUCCESS;` |
|
||||
| *EXIT_FAILURE* | *stdlib.h* | Value the program should return on exit with error. | `return EXIT_FAILURE;` |
|
||||
| *sin(x)* | *math.h* | Returns [sine](sin.md) of angle in [RADIANS](rad.md). | `float angleSin = sin(angle);` |
|
||||
| *cos(x)* | *math.h* | Like `sin` but returns cosine. | `float angleCos = cos(angle);` |
|
||||
| *tan(x)* | *math.h* | Returns [tangent](tan.md) of angle in RADIANS. | `float angleTan = tan(angle);` |
|
||||
| *asin(x)* | *math.h* | Returns arcus sine of angle, in RADIANS. | `float angle = asin(angleSine);` |
|
||||
| *ceil(x)* | *math.h* | Rounds a floating point value up. | `double x = ceil(y);` |
|
||||
| *floor(x)* | *math.h* | Rounds a floating point value down. | `double x = floor(y);` |
|
||||
| *fmod(a,b)* | *math.h* | Returns floating point reminded after division. | `double rem = modf(x,3.5);` |
|
||||
| *isnan(x)* | *math.h* | Checks if given float value is NaN. | `if (!isnan(x))` |
|
||||
| *NAN* | *math.h* | Float quiet [NaN](nan.md) (not a number) value, don't compare! | `if (y == 0) return NAN;` |
|
||||
| *log(x)* | *math.h* | Computes natural [logarithm](log.md) (base [e](e.md)). | `double x = log(y);` |
|
||||
| *log10(x)* | *math.h* | Computes decadic [logarithm](log.md) (base 10). | `double x = log10(y);` |
|
||||
| *log2(x)* | *math.h* | Computes binary [logarithm](log.md) (base 2). | `double x = log2(y);` |
|
||||
| *exp(x)* | *math.h* | Computes exponential function (*e^x*). | `double x = exp(y);` |
|
||||
| *sqrt(x)* | *math.h* | Computes floating point [square root](sqrt.md). | `double dist = sqrt(dx * dx + dy * dy);` |
|
||||
| *pow(a,b)* | *math.h* | Power, raises *a* to *b* (both floating point). | `double cubeRoot = pow(var,1.0/3.0);` |
|
||||
| *abs(x)* | *math.h* | Computes [absolute value](abs.md). | `double varAbs = abs(var);` |
|
||||
| *INT_MAX* | *limits.h* | Maximum value that can be stored in `int` type. | `printf("int max: %d\n",INT_MAX);` |
|
||||
| *memset(mem,val,size)* | *string.h* | Fills block of memory with given values. | `memset(myArr,0,sizeof(myArr));` |
|
||||
| *memcpy(dest,src,size)* | *string.h* | Copies bytes of memory from one place to another, returns dest. | `memcpy(destArr,srcArr,sizeof(srcArr);` |
|
||||
| *strcpy(dest,src)* | *string.h* | Copies string (zero terminated) to dest, unsafe. | `char myStr[16]; strcpy(myStr,"hello");` |
|
||||
| *strncpy(dest,src,n)* | *string.h* | Like `strcpy` but limits max number of bytes to copy, safer. |`strncpy(destStr,srcStr,sizeof(destStr));`|
|
||||
| *strcmp(s1,s2)* | *string.h* | Compares two strings, returns 0 if equal. | `if (!strcmp(str1,"something"))` |
|
||||
| *strlen(str)* | *string.h* | Returns length of given string. | `int l = strlen(myStr);` |
|
||||
| *strstr(str,substr)* | *string.h* | Finds substring in string, returns pointer to it (or NULL). | `if (strstr(cmdStr,"quit") != NULL)` |
|
||||
| *time(t)* | *time.h* |Stores calendar time (often Unix t.) in t (can be NULL), returns it.|`printf("tstamp: %d\n",(int) time(NULL));`|
|
||||
| *clock()* | *time.h* | Returns approx. CPU cycle count since program start. |`printf("CPU ticks: %d\n",(int) clock());`|
|
||||
| *CLOCKS_PER_SEC* | *time.h* | Number of CPU ticks per second. |`int sElapsed = clock() / CLOCKS_PER_SEC;`|
|
||||
|
||||
## Some Programs In C
|
||||
|
||||
TODO
|
||||
|
||||
## See Also
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue