switched txt to md
This commit is contained in:
parent
0d4dc438e6
commit
f8b6995add
1 changed files with 0 additions and 0 deletions
213
qfetchC-notes.md
Normal file
213
qfetchC-notes.md
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
## The mindset shift: C vs C++
|
||||
|
||||
In C:
|
||||
|
||||
- ❌ No classes, no RAII, no `std::string`
|
||||
- ✅ **You control memory explicitly**
|
||||
- ✅ Functions are small, focused, and composable
|
||||
- ✅ Portability comes from *conditional compilation*
|
||||
|
||||
- “Each function returns ownership of dynamically allocated data, and the caller frees it.”*
|
||||
|
||||
## Feature macros (`_POSIX_C_SOURCE`)
|
||||
|
||||
```c
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
```
|
||||
|
||||
### Why this exists
|
||||
|
||||
C standard libraries hide some functions unless you *opt in*.
|
||||
|
||||
Without it:
|
||||
|
||||
* Some systems won’t expose those functions
|
||||
* You’ll get mysterious warnings or missing symbols
|
||||
|
||||
---
|
||||
|
||||
## Headers: what C teaches you here
|
||||
|
||||
```c
|
||||
#include <stdio.h> // printf, FILE
|
||||
#include <stdlib.h> // malloc, free
|
||||
#include <string.h> // strlen, strdup
|
||||
#include <unistd.h> // POSIX functions
|
||||
```
|
||||
|
||||
In C:
|
||||
|
||||
* Headers are **contracts**
|
||||
* If it’s not included, the compiler assumes *nothing*
|
||||
|
||||
**Rule of thumb:**
|
||||
|
||||
> If you call a function, its header must be included — no exceptions.
|
||||
|
||||
---
|
||||
|
||||
## Conditional compilation (`#if defined(...)`)
|
||||
|
||||
Example:
|
||||
|
||||
```c
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
```
|
||||
|
||||
### What this teaches you
|
||||
|
||||
* C has **no runtime reflection**
|
||||
* Portability happens at **compile time**
|
||||
* The preprocessor literally removes code before compilation
|
||||
|
||||
Think of it as:
|
||||
|
||||
```text
|
||||
“Only compile this code if the OS supports it.”
|
||||
```
|
||||
|
||||
This is how *real* portable C software works (git, curl, openssh).
|
||||
|
||||
---
|
||||
|
||||
## The most important function in the file
|
||||
|
||||
```c
|
||||
static char *dup_or_unknown(const char *s)
|
||||
```
|
||||
|
||||
### Why this exists
|
||||
|
||||
This function enforces a **contract**:
|
||||
|
||||
* Every getter:
|
||||
|
||||
* returns a valid `char *`
|
||||
* never returns `NULL`
|
||||
* always returns heap memory
|
||||
|
||||
### Why that matters
|
||||
|
||||
It lets `main()` be *simple*:
|
||||
|
||||
```c
|
||||
char *user = get_user();
|
||||
/* ... */
|
||||
free(user);
|
||||
```
|
||||
|
||||
No special cases.
|
||||
No defensive `if (ptr)` checks.
|
||||
|
||||
---
|
||||
|
||||
## Dynamic allocation patterns (CRITICAL)
|
||||
|
||||
Example:
|
||||
|
||||
```c
|
||||
char *buf = malloc(len);
|
||||
snprintf(buf, len, "...", ...);
|
||||
return buf;
|
||||
```
|
||||
|
||||
### This is idiomatic C
|
||||
|
||||
Rules being followed:
|
||||
|
||||
1. Allocate **exactly what you need**
|
||||
2. Initialize before use
|
||||
3. Return ownership to the caller
|
||||
4. Caller must `free()`
|
||||
|
||||
Contrast this with C++:
|
||||
|
||||
* No destructors
|
||||
* No smart pointers
|
||||
* No safety net
|
||||
|
||||
---
|
||||
|
||||
## Why no global buffers?
|
||||
|
||||
You *could* have done:
|
||||
|
||||
```c
|
||||
static char buf[256];
|
||||
```
|
||||
|
||||
But that would:
|
||||
|
||||
* Break thread safety
|
||||
* Break reentrancy
|
||||
* Make functions non-composable
|
||||
|
||||
Dynamic allocation makes your functions:
|
||||
|
||||
* Reusable
|
||||
* Testable
|
||||
* Library-quality
|
||||
|
||||
---
|
||||
|
||||
## Reading system information in C
|
||||
|
||||
Each platform teaches a lesson:
|
||||
|
||||
### Linux
|
||||
|
||||
```c
|
||||
/proc/cpuinfo
|
||||
/proc/uptime
|
||||
```
|
||||
|
||||
* Text parsing
|
||||
* Line-by-line scanning
|
||||
* Defensive string handling
|
||||
|
||||
### macOS / BSD
|
||||
|
||||
```c
|
||||
sysctl()
|
||||
```
|
||||
|
||||
* Structured kernel APIs
|
||||
* Buffer-size negotiation
|
||||
* Integer & struct-based data
|
||||
|
||||
---
|
||||
|
||||
## Time handling (classic C pain point)
|
||||
|
||||
```c
|
||||
time_t now = time(NULL);
|
||||
difftime(now, boottime.tv_sec);
|
||||
```
|
||||
|
||||
Why this matters:
|
||||
|
||||
* `time_t` may not be an integer
|
||||
* You *never* subtract times directly
|
||||
* `difftime()` handles portability
|
||||
|
||||
---
|
||||
|
||||
## The `main()` function: clean by design
|
||||
|
||||
```c
|
||||
char *user = get_user();
|
||||
/* ... */
|
||||
free(user);
|
||||
```
|
||||
|
||||
Notice:
|
||||
|
||||
* No logic
|
||||
* No parsing
|
||||
* No platform checks
|
||||
* No error handling clutter
|
||||
|
||||
All complexity lives *outside* `main()`.
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue