| sizeof | strlen | |
|---|---|---|
| 性質 | 編譯期運算符 | 運行期函數 |
| 返回值 | 類型/對象佔用**位元組數** | 字串**字符數** (不含 \0) |
| 陣列參數 | **不退化**,得整個陣列大小 | 退化為指針,得字串長度 |
| 指針參數 | 得指針大小 (4/8) | 得字串長度 |
char *src = "hello world";
char *dest = NULL;
int len = strlen(src); // 正確:11
// int len = sizeof(src); // 錯誤:得 4/8 (指針大小)
dest = (char*)malloc(len + 1); // +1 留給 \0
// dest = malloc(len); // 錯誤:漏掉結束符空間
char *d = dest;
char *s = &src[len - 1]; // 指向最後一個字符
while (len-- != 0) *d++ = *s--; // 反向複製
*d = '\0'; // 必須手動添加結束符
printf("%s\n", dest); // "dlrow olleh"
free(dest); // 必須配對釋放
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a + 1); // &a 是 int(*)[5],+1 跳過整個陣列
printf("%d, %d\n", *(a+1), *(ptr-1)); // 2, 5
&a 類型為「指向 5 個 int 陣列的指針」,步長 = sizeof(a) = 20 字節。ptr - 1 回退到陣列最後一個元素 a[4]。
void show(const char **pp) { printf("%s\n", *pp); }
char array[4] = "abc"; // char[4]
char *pointer = "abc"; // char*
show(&pointer); // OK:&pointer 是 char**
show(&array); // 錯誤:&array 是 char(*)[4],非 char** → 輸出亂碼
**結論**:陣列名在**表達式**中多數退化為指針,但 sizeof、&、_Alignof 等運算符**不退化**。
int a[1000000]; → **棧溢出**(默認棧 1~8 MB,int 4 bytes → 4 MB 超限)。int *p = malloc(1000000 * sizeof(int)); → **堆分配**,僅受限於虛擬記憶體/碎片。static int a[250000]; 放在 .bss 段,不佔棧空間。fprintf(fp, "%d", a[i]); 寫入 ASCII 碼。
FILE *fp = fopen("out.dat", "wb"); // "wb" 二進制寫
fwrite(&a, sizeof(int), 1, fp); // 寫入 4 字節原始位模式
fclose(fp);
fp = fopen("out.dat", "rb"); // "rb" 二進制讀
fread(&b, sizeof(int), N, fp); // 直接讀回 int
fclose(fp);
⚠️ **切勿**用 fprintf(fp, "%d", ...) 寫二進制文件,會產生可讀文本而非原始位模式。
| 算法 | 18 萬元素耗時 | 最大安全元素數 |
|---|---|---|
| 快速排序 (首中尾取中優化) | 0.497 s | ~3 萬 |
| VC6 qsort() | 1.942 s | 較大 |
| 堆排序 | 0.032 s | 無棧限制 |
| 希爾排序 (優化版) | 8.518 s | 無棧限制 |
每次遞歸調用在棧上壓入:返回地址、參數、局部變量、保存的寄存器。
Fac(3) → 3*Fac(2) 入棧 → 2*Fac(1) 入棧 → 返回展開。
**棧幀大小 × 遞歸深度 = 總棧消耗**。
std::sort (內部混合非遞歸)。std::vector/數組做棧)。/STACK、pthread_attr_setstacksize)。strlen,對象大小用 sizeof,絕不混用。malloc 大小用 sizeof(Type) * N,記得 +1 給字串結束符。fread/fwrite + "rb"/"wb"。sizeof 失效,需額外傳長度。-Wall -Wextra -pedantic / /W4),靜態分析工具 (Cppcheck, Clang Static Analyzer) 定期掃描。