> See also:
> - Reference
# C Programming Language
`echo $?` - returns error code of past output statement
### TODO Review
- Static array vs pointer array
## Basic Variable Types
| Name | Syntax | Byte Size | Description |
| --- | --- | --- | --- |
| Character | `char` | 1 | Stores a single ASCII character |
| Integer | `int` | 4 | |
| Float | `float` | 4 | |
| Double | `double` | 8 | |
Any non-zero value in C is viewed as "True"
### Arrays
arrays = pointers
This is important to remember when accessing a variable's values
### Strings
A **string** in C is an array of `char` variables followed by a terminator `\0` element.
- It's useful to write `num + 1` when defining strings to track the proper length
`fgets(char *destination, int string_size, FILE *stream*)`
### Pointers
`*var` - The `*` symbol indicates the value being stored (called “*dereferencing*”)
`&var` - The `&` symbol indicates a memory address location
Pointers are statically created, meaning that you cannot change the specific memory address f
### Structures
`struct.attribute`
`struct_ptr->attribute`
The variables stored within a struct are typically referred to as components
## Basic Input/Output
**Buffers** are generally described as temporary variables used to temporarily allocate memory for a specific task.
### String Inputs
## Dynamic Memory
**Static Memory:**
- A specific amount of provided to a program when it is run
- This memory space cannot be increased or reduced, making it
**Dynamic Memory:**
- Stored in heap space
Nearly all of the foundational functions for dynamic memory are within the `stdlib` library.
When specifying the size of the memory, these functions use a `size_t` variable type. This is an unsigned integer (meaning that negative inputs will result in integer underflow).
---
`malloc(size_t memory_size)`
- It's good to use the `sizeof()` function to determine the necessary memory size as variable sizes can vary based on system architecture
- Returns a void pointer (`void *`) and should be type-cast
- Returns `NULL *` on fail
```c
int * arr = (int *)malloc(10 * sizeof(int));
if (arr == NULL) {
// handle fail state
}
```
---
`realloc(void *, size_t n)`
- Used when you need to modify (increase) the size of dynamically allocated memory
- Fills new memory space with garbage values
- Automatically frees old memory section
- Returns a void pointer (`void *`) and should be type-cast
```c
int * arr = (int *)realloc(void * orig_dyn_pntr, 10 * sizeof(int))
if (arr != NULL) {
// desired behavior
} else {
// handle fail state
}
```
---
`calloc(size_t num_of_items, size_t size_of_items)`
- Automatically initializes the values within the memory to byte-wise `0`
```c
int * arr = (int *)calloc(void * orig_dyn_pntr, size_of_items)
```
---
`free(void * ptr_to_heap_mem)`
- Make sure to never free static memory
```c
free(void * ptr_to_heap_mem)
```
- `free(NULL)` does nothing
### Dynamic Memory Violations
> [!danger] **Memory Violations (In C Language)**
> 1. Double `free()`
> 2. Attempting to use a pointer
>
- Never free the same heap space pointer twice
- Don't use a freed pointer after using the free() function
- Freeing static memory
-
debugging:
`gcc [c file] -g`
`valgrind [program]`