C 語言複雜知識點
編譯與巨集
#
開頭為預處理命令,包括 #include
引入檔案 #define
巨集,在預處理階段處理
函式宣告與語法檢測在編譯期檢查,函式定義在連結時檢測
__attribute__(constructor))
有該巨集上標的函式先於 main
執行
#include <stdbool.h>
使得 c 支援 bool
型別
extern
引用其他檔案已定義過的全域性變數
__typeof()
巨集獲得變數型別,常用於定義巨集
#define swap(a, b) {\
__typeof(a) __temp = a;\
a = b; b = __temp;\
}
// 或者 a ^= b; b ^= a; a ^= b;
// 根據變數型別,獲得指定輸出
#define Type(a) _Generic((a), \
int : "%d",\
double : "%lf",\
float : "%f",\
long long : "%ld",\
const char * : "%s",\
char * : "%s"\
)
EOF
巨集常量為 -1, NULL
為 0
變參函式引入 stdarg.h
#include <stdarg.h>
int max(int num, ...) {
va_list arg; // 宣告引數
va_start(arg, num); // 使得 arg 指向起始引數
while (num--) { // num 幫助判斷引數個數
int temp = va_arg(arg, int); // 開始獲得改型別的引數
}
va_end(arg); // 釋放 va_list
}
// 可通過 myprintf(const char *frm, ...) 自己實現列印函式
// 防止多次引入標頭檔案巨集重複宣告
#ifndef _LOG_H
#define _LOG_H
// 通過標頭檔案編譯列印技巧
#ifdef DEBUG
#define log(frm, args...) { \
printf("[%s : %s : %d]", __FILE__, __func__, __LINE__); \
printf(frm, ##args); \
printf("\n"); \
}
#else
#define log(frm, args...)
#endif
#define contact(a, b) a##b // 拼接合並 一個#變成字元常量
#endif
工程開發規範,.h
標頭檔案放函式宣告,.c
檔案放函式定義,標頭檔案和原始檔分離,可以解決函式定義引用函式找不到的問題
工程專案目錄編排:
src
原始碼目錄lib
外部庫目錄 可用靜態庫檔案lib*.a
include
標頭檔案.h
bin
可執行檔案build
構建過程中間檔案(可選)
makefile
檔案
.PHONY: clean // 虛擬 clean 檔案,不檢查
all: lib/lib1.a test.o // 依賴
gcc test.o -L./lib -llib1 -DDEBUG // 指定庫 開啟巨集宣告
test.o: test.cpp
gcc -I./include -c test.cpp // -c 不連結
clean:
rm -rf a.out test.o // 清理
語言特性與庫
c 語言中的 switch
只能判斷整型值變數
math.h
中返回和傳參都是高精度
需要了解的一個最大公約數函式
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
printf
scanf
返回值為讀入長度
對於 scanf
函式,我們可以通過 scanf("%[^\n]s", str)
來跳過換行輸入等
sprintf
以指定格式列印到字串,sscanf
從字串中讀出型別變數
c 語言中自帶 stdin
stdout
stderr
檔案符,對檔案進行操作
FILE *fout = fopen("output", "w");
fprintf(stdout, "stdout = %s\n", str);
fprintf(fout, "fout = %s\n", str); // 寫入檔案
fclose(fout); // 注意關閉檔案
使用隨機數,引入 time.h
#include <time.h>
srand(time(0));
int val = rand() % 100; // 0 - 100 的隨機數
使用動態記憶體函式,引入 stdlib.h
函式指標也是引數,可進行傳參呼叫指定方法函式
double newton(double (*F)(double, double), double(*f)(double), double n);
// main 傳入引數個數,引數陣列,環境變數
int argc, char *argv[], char **env
指標、堆疊空間、結構體
const int *x
指標常量 int * const x
常量指標
函式內宣告的變數在棧空間中,所以需要 malloc
指標等幫助下在堆空間建立,傳出去,棧空間內的變數會被銷燬
結構體成員描述關係會影響結構體構造的函式大小,比如 char
可能跟記憶體對齊 4 個位元組 或 8 位元組 (看系統)
自定義巨集,檢視結構體成員偏移
#define offset(T, a) (long) (&(((T *) (NULL))->a))
64 位系統指標變數大小是 8 位元組,32 位系統指標變數大小為 4 位元組
指標根據宣告型別去跳位,p++
char
型別跳 8 位,int
型別跳 32 位
float
佔 4 位元組,double
佔 8 位元組,long long
佔 8 位元組
對於函式指標,我們可以通過 typedef
函式提升至型別,方便呼叫
記憶體洩漏,宣告一塊記憶體後,對其訪問丟失,沒有釋放
函式系統棧空間不超過 8MB,函式結束時釋放
在程式碼中出現的所有同樣的字串,都是字串常量,指向同一靜態區
對於常量,全域性變數,靜態變數(即使在函式內)都存在靜態區,程式結束釋放
static
在 c 語言的作用主要是隱藏,不讓在檔案外匯出;唯一一次初始化(在程式啟動時,函式中不會初始化它),保持變數的持久;預設設定為 0
申請記憶體函式申請的都是虛擬記憶體,在虛地址上
malloc
申請後,在實際訪問情況下時若記憶體不夠才嘗試缺頁異常;不會對原記憶體內容進行修改
calloc
在申請記憶體後,立刻把原記憶體中的內容置 0 了,進行了訪問
realloc
在當前指標上,基於原記憶體地址擴充
共用體中所有元素公用一個空間,一般機器都是大端模式
union IP {
struct {
unsigned char a1;
unsigned char a2;
unsigned char a3;
unsigned char a4;
} ip;
unsigned int num;
};
相關文章
- c語言常用小知識點總結1C語言
- C語言知識彙總 | 00-C語言知識彙總目錄C語言
- c語言基礎知識C語言
- C語言瑣碎知識C語言
- c語言基礎知識3C語言
- C語言指標基本知識C語言指標
- 那些主流程式語言的知識,C語言(Ⅰ)C語言
- 、【C語言基礎】 第十天 | 知識點總結C語言
- c語言複習C語言
- Generator知識點雜燴
- Netty知識點(雜記)Netty
- 【C/C++】C語言基礎知識【第二版】C++C語言
- 易被忽略的知識點之 ---- 各種時間複雜度和空間複雜度時間複雜度
- C/C++期末考試複習---知識點+習題C++
- C語言知識彙總 | 51-C語言字串指標(指向字串的指標)C語言字串指標
- C語言知識彙總 | 56-C語言NULL空指標以及void指標C語言Null指標
- 初識C語言C語言
- C語言語句知識結構大學霸IT達人C語言
- c++知識點C++
- 雜湊表知識點小結
- c語言之解釋複雜指標C語言指標
- 【建議收藏】Go語言關鍵知識點總結Go
- C++基本知識點C++
- 1. 時間複雜度和空間複雜度 (7 天掌握演算法面試必考知識點)時間複雜度演算法面試
- C語言期末複習資料C語言
- C語言位運算子知識總結和例項分析C語言
- C語言函式知識體系大學霸IT達人C語言函式
- flutter【1】-dart語言--基本知識FlutterDart
- 【技術性】OO語言知識
- 組合語言-基礎知識組合語言
- 那些年忽略的知識:時間複雜度和空間複雜度詳解時間複雜度
- 資料結構雜湊表(c語言)資料結構C語言
- 【C++】 C++知識點總結C++
- C++引用全部知識點C++
- 【必知必會的MySQL知識】④DCL語言MySql
- 【必知必會的MySQL知識】⑤DQL語言MySql
- 【必知必會的MySQL知識】③DML語言MySql
- C語言陣列知識體系整理大學霸IT達人C語言陣列