ece150: add everything new

This commit is contained in:
eggy 2022-10-23 16:57:16 -04:00
parent 1f3ec71cd6
commit 05402d542e

View File

@ -1,5 +1,171 @@
# ECE 150: C++
## Call stack
## Non-decimal numbers
Binary numbers are prefixed with `0b`.
!!! example
The following two snippets are equivalent:
```cpp
int a{0b110001};
```
```cpp
int a{25};
```
To convert from **binary to decimal**, each digit should be treated as a power of two much like in the base 10 system.
!!! example
$$
\text{0b1011}=1\times2^3 + 0\times2^2+1\times2^1+1\times2^0=11
$$
Binary addition is the same as decimal addition except $1+1=10$ and $1+1+1=11$.
To convert from **decimal to binary**, the number should be repeatedly divided by 2 and the binary number taken from the remainders from bottom to top.
!!! example
$$
\begin{align*}
13 &= 2\times6 + 1 \\
6 &= 2\times3 + 0 \\
3 &= 2\times1 + 1 \\
1 &= 2\times0 + 1
\\
&\therefore 13 = \text{0b1101}
\end{align*}
$$
To convert from **binary to hexadecimal**, each group of four digits beginning from the right should be converted to their hexadecimal representation.
To convert from **hexadecimal to binary**, each hexadecimal digit should be expanded into its four-digit binary representation.
To convert from **decimal to hexadecimal**, the number should be repeatedly divided by 16 and the hex number taken from the remainders from bottom to top.
!!! example
$$
\begin{align*}
37 &= 16\times2 + 5 \\
2 &= 16\times0 + 2
\\
&\therefore 37 = \text{0x25}
\end{align*}
$$
## Numbers
### Integers
!!! definition
- A **carry** occurs if an overflow or underflow happens in an unsigned number.
The $k$th bit of a number is as known as its **coefficient** because it can be expressed in the form $n\times 2^k$ in binary or $n\times 16^k$ in hexadecimal.
| Type | Bits | Can store |
| --- | --- | --- |
| `short` | 16 | $\pm2^{15}-1$ |
| `int` | 32 | $\pm2^{31}-1$ |
| `long` | 64 | $\pm2^{63}-1$ |
| `char` | 8 | N/A |
| `unsigned short` | 16 | $2^{16}-1$ |
| `unsigned int` | 32 | $2^{32}-1$ |
| `unsigned long` | 64 | $2^{64}-1$ |
| `unsigned char` | 8 | N/A |
The `sizeof()` operator evaluates the size the type takes in memory at compile time.
Signed numbers use the first bit to represent positive or negative numbers. A negative number is equal to the **two's complement** of its positive form. This allows subtraction to be done by taking the two's complement of the subtracter.
!!! definition
The two's complement form of a number flips all bits **but the rightmost digit equal to one**.
### Floating point numbers
| Type | Bits | Digits of precision |
| --- | --- | --- |
| `float` | 32 | ~7 |
| `double` | 64 | ~16 |
Floating point numbers let a computer work with numbers of arbitrary precision. However, the limited digits of precision mean that a small number added to a large number can result in the number not changing. This results in odd scenarios such as:
$$
x+(y+z)\neq(x+y)+z
$$
## References
The ampersand (&) represents a reference variable and an argument passed into a parameter with an ampersand must be a valid lvalue.
Effectively, it is a pointer, letting you do weird shit such as:
```cpp
void inc(int &n) {
n++;
}
```
where the variable passed into `inc` will actually increase in the caller function.
This can also be used in variable declarations to not create a second local variable:
```cpp
#include <climits>
double const &pi{M_PI}; // pi links back to M_PI
```
## Arrays
```cpp
// typename identifier[n]{};
int array[5]{};
int partial[3]{2};
int filled[3]{1, 2, 3};
```
Arrays are contiguous in memory and default to 0 when initialised. If field initialised with values, the array will fill the first values as those values and set the rest to 0.
Because arrays do not check bounds, `array[n+10]` or `array[-5]` will go to the memory address directed without complaint and ruin your day.
### Local arrays
Local arrays cannot be assigned to nor returned from a function. If an array is marked `const`, its entries cannot be modified.
Arrays can be passed to functions by reference (via pointer to the first entry).
## Memory
!!! definition
- **Volatile** memory is erased after the memory is powered off.
- **Byte-addressable** memory is memory that has an address for each byte, such that to change a single bit the whole byte must be rewritten.
Main memory (random access memory, RAM) is volatile and any location in the memory has the same access speed.
An **address bus** with $n$ lines allows the CPU to update $n/8$ bytes at once (one address bit per line). The number of total memory addresses is limited by the number of lanes in the address bus.
When a program is run, the operating system (OS) allocates a block of memory for it such that the largest address is at the bottom of the memory block for the program.
- Instructions (the **code segment**) are stored at the **top** of the block
- Constants (the **data segment**, including string literals) are stored **after** the instructions
- Local variables (the **call stack**) are stored beginning from the **bottom** of the block
Dynamically allocated variables and static variables are stored between the call stack and the data segment.
### Call stack
The call stack represents memory and variables are allocated space from bottom to top.
At the moment a function is run, its parameters are allocated space at the bottom, followed by all local variables that **may or may not** be defined.
The return value of the function overwrites whatever is at the bottom of the function-allocated block such that the caller can simply reach up to get return data.
!!! warning
Arrays are allocated **top-down** such that indexing is made easy.
## C-style strings
C-style strings are char arrays that end with a **null terminator** (`\0`). By default, char arrays are initialised with this character.
If there is not a null terminator, attempting to access a string continues to go down the call stack until a zero byte is found.