目錄
- 結構體的字節對齊
- 預處理指令詳解
- 文件操作基礎
- Makefile自動化構建
- 總結
1. 結構體的字節對齊
字節對齊原理
- 內存對齊:CPU訪問內存時,對齊的地址能提高效率。操作系統要求變量按類型大小對齊。
- 對齊規則:
- 每個成員的起始地址必須是
min(成員類型大小, #pragma pack(n))
的整數倍。 - 結構體總大小必須是最大成員對齊值的整數倍。
- 嵌套結構體需遵循相同規則。
- 每個成員的起始地址必須是
示例分析
示例1
struct Test {int a; // 4字節char b; // 1字節
};
// 默認對齊(假設為4字節):
// 總大小 = 4(int) + 3字節填充 + 1(char) = 8字節
示例2(嵌套結構體)
struct A {double a; // 8字節short b; // 2字節
};struct Test {char a[20]; // 20字節int c; // 4字節struct A d; // 12字節(8+4填充)char b; // 1字節
};
// 總大小:20 + 4 + 12 + 1 + 3填充 = 40字節
調整對齊方式
#pragma pack(n)
:手動設置對齊粒度。#pragma pack(1) // 緊湊存儲 struct Test {char a; // 1字節int b; // 4字節(無填充) }; #pragma pack() // 恢復默認
2. 預處理指令詳解
預處理階段
- 作用:宏定義、頭文件包含、條件編譯等。
- 流程:預處理 → 編譯 → 匯編 → 鏈接。
頭文件包含
- 區別:
#include <stdio.h>
:系統頭文件。#include "test.h"
:當前目錄或自定義路徑。
頭文件重復包含防護
#ifndef _TEST_H_
#define _TEST_H_
// 頭文件內容
#endif
宏定義與條件編譯
無參宏
#define PI 3.14
#undef PI // 取消定義
有參宏
#define MUL(x,y) ((x)*(y)) // 避免運算優先級問題
#define ADD(x,y) (x + y)
條件編譯
#ifdef DEBUGprintf("Debug mode\n");
#elseprintf("Release mode\n");
#endif
3. 文件操作基礎
文件操作模式
模式 | 描述 | 示例模式 |
---|---|---|
r | 只讀文本文件 | fopen("file.txt", "r") |
w | 只寫文本文件(覆蓋) | fopen("file.txt", "w") |
a | 追加文本文件 | fopen("file.txt", "a") |
rb | 只讀二進制文件 | fopen("file.dat", "rb") |
wb | 只寫二進制文件(覆蓋) | fopen("file.dat", "wb") |
字符與字符串讀寫
fgetc/fputc
FILE *fp = fopen("file.txt", "w");
fputc('A', fp); // 寫入字符'A'
fclose(fp);
feof判斷文件結束
char ch;
FILE *fp = fopen("file.txt", "r");
while ((ch = fgetc(fp)) != EOF) { // EOF表示文件結束printf("%c", ch);
}
fclose(fp);
fgets/fputs按行讀寫
// 寫入
fputs("Hello World\n", fp);
// 讀取
char buf[256];
fgets(buf, sizeof(buf), fp); // 讀取一行,自動添加'\0'
格式化讀寫(fprintf/fscanf)
// 寫入
fprintf(fp, "a=%d,b=%.2f\n", 100, 3.14);
// 讀取
int a;
float b;
fscanf(fp, "a=%d,b=%f", &a, &b);
二進制文件操作(fread/fwrite)
typedef struct {char name[20];int id;
} STU;STU students[3] = { /* 初始化數據 */ };
// 寫入
FILE *fp = fopen("data.dat", "wb");
fwrite(students, sizeof(STU), 3, fp);
fclose(fp);// 讀取
STU read_data[3];
fp = fopen("data.dat", "rb");
fread(read_data, sizeof(STU), 3, fp);
fclose(fp);
文件隨機讀寫
-
定位文件指針:
fseek(fp, 50, SEEK_SET); // 從文件頭移動50字節 fseek(fp, -50, SEEK_END); // 從文件尾回退50字節
-
獲取當前位置:
long pos = ftell(fp); // 當前位置偏移量 rewind(fp); // 快速回到文件開頭
4. Makefile自動化構建
Makefile基礎規則
# 目標依賴規則
main: main.o add.o sub.ogcc main.o add.o sub.o -o mainmain.o: main.cgcc -c main.c
變量與自動變量
- 普通變量:
CC = gcc CFLAGS = -Wall -g
- 自動變量:
$@
:目標文件名$^
:所有依賴文件$<
:第一個依賴文件
模式規則與函數
# 通用編譯規則
%.o: %.c$(CC) -c $< -o $@ $(CFLAGS)# 查找所有.c文件
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
多文件項目示例
DIR_SRC = ./src
DIR_OBJ = ./obj
SRCS = $(wildcard $(DIR_SRC)/*.c)
OBJS = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))main: $(OBJS)$(CC) $^ -o main$(DIR_OBJ)/%.o: $(DIR_SRC)/%.c$(CC) -c $< -o $@ -I./include.PHONY: clean
clean:rm -rf $(DIR_OBJ)/*.o main
5. 總結
- 結構體對齊:通過
#pragma pack
優化內存布局,避免內存浪費。 - 預處理:宏定義提升代碼復用性,條件編譯增強跨平臺兼容性。
- 文件操作:區分文本與二進制模式,靈活使用
fseek
和ftell
實現隨機讀寫。 - Makefile:自動化構建簡化編譯流程,支持多文件項目管理。
希望這篇博客能幫助你系統掌握C語言核心知識點!如果有疑問或需要進一步解釋,歡迎在評論區交流!