// complete reference

C Language

Cheat Sheet

// C89 · C99 · C11 · C17 标准全覆盖

01 / 基础结构 & 数据类型
程序基本结构
#include <stdio.h>
#include <stdlib.h>

/* 函数声明(原型) */
int add(int a, int b);

int main(int argc, char *argv[]) {
    printf("Hello, World!\n");
    return 0;
}

int add(int a, int b) {
    return a + b;
}
基本数据类型
类型大小范围 / 说明
char1 B-128 ~ 127
unsigned char1 B0 ~ 255
short2 B-32768 ~ 32767
int4 B-2³¹ ~ 2³¹-1
long4/8 B平台相关
long long8 B-2⁶³ ~ 2⁶³-1
float4 B~7 位有效数字
double8 B~15 位有效数字
long double8/16 B扩展精度
_Bool (bool)1 B0 或 1(C99)
void无类型
变量声明 & 初始化
/* 基本声明 */
int a = 10;
float f = 3.14f;
double d = 3.14159;
char c = 'A';
char s[] = "Hello";

/* 限定符 */
const int MAX = 100;    // 只读
volatile int flag;      // 防优化
static int count = 0;  // 持久/内部
extern int global;     // 外部声明

/* C99 固定宽度整数 */
#include <stdint.h>
int8_t  i8  = -1;
uint32_t u32 = 0xDEADBEEF;
int64_t i64 = 1LL;
size_t  sz  = sizeof(int);
类型转换
/* 隐式转换(自动提升) */
int i = 42;
double d = i;          // int → double

/* 显式强制转换 */
double pi = 3.14159;
int n = (int)pi;       // 3(截断)

int a = 7, b = 2;
double r = (double)a / b; // 3.5

/* 整数字面量后缀 */
long      lv  = 100L;
long long llv = 100LL;
unsigned  uv  = 100U;
float     fv  = 1.0f;
long double ldf = 1.0L;
02 / 运算符
算术 & 赋值运算符
int a = 10, b = 3;
a + b    // 13   加法
a - b    // 7    减法
a * b    // 30   乘法
a / b    // 3    整除
a % b    // 1    取余
-a       // -10  取负
++a      // 11   前置自增
a++      // 先用后增
--a      // 前置自减

/* 复合赋值 */
a += b;  a -= b;  a *= b;
a /= b;  a %= b;
比较 & 逻辑 & 位运算
/* 比较运算符(返回 0/1) */
a == b   a != b
a <  b   a <= b
a >  b   a >= b

/* 逻辑运算符 */
a && b   // 逻辑与(短路)
a || b   // 逻辑或(短路)
!a       // 逻辑非

/* 位运算符 */
a & b    // 按位与
a | b    // 按位或
a ^ b    // 按位异或
~a       // 按位取反
a << 2   // 左移2位
a >> 1   // 右移1位

/* 三目运算符 */
int max = (a > b) ? a : b;
运算符优先级(高→低)
优先级运算符
1 最高() [] -> . ++ --(后缀)
2++ -- + - ! ~ * & (type) sizeof(前缀/一元)
3* / %
4+ -
5<< >>
6< <= > >=
7== !=
8-10& ^ |
11-12&& ||
13? :
14= += -= *= /= %= &= ^= |= <<= >>=
15 最低,(逗号)
03 / 控制流
条件语句
/* if / else if / else */
if (x > 0) {
    printf("正数\n");
} else if (x < 0) {
    printf("负数\n");
} else {
    printf("零\n");
}

/* switch / case */
switch (ch) {
    case 'a':
    case 'A':
        puts("字母A");
        break;
    case 'b':
        puts("字母B");
        break;
    default:
        puts("其他");
}
循环语句
/* for 循环 */
for (int i = 0; i < 10; i++) {
    printf("%d ", i);
}

/* while 循环 */
int n = 5;
while (n > 0) {
    printf("%d\n", n--);
}

/* do-while(至少执行一次)*/
int x;
do {
    scanf("%d", &x);
} while (x <= 0);

/* 控制跳转 */
break;      // 退出循环/switch
continue;   // 跳到下次迭代
goto label; // 无条件跳转
label: ;
04 / 函数
函数定义 & 调用
/* 函数原型 */
int max(int a, int b);
void greet(const char *name);
double power(double base, int exp);

/* 函数定义 */
int max(int a, int b) {
    return (a > b) ? a : b;
}

/* 递归 */
int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

/* 可变参数 */
#include <stdarg.h>
int sum(int count, ...) {
    va_list args;
    va_start(args, count);
    int total = 0;
    for (int i = 0; i < count; i++)
        total += va_arg(args, int);
    va_end(args);
    return total;
}
函数指针
/* 声明:返回类型 (*名称)(参数类型) */
int (*fp)(int, int);

/* 赋值与调用 */
fp = max;
int r = fp(3, 5);   // 或 (*fp)(3,5)

/* 作为参数(回调) */
void apply(int *arr, int n,
           void (*fn)(int)) {
    for (int i = 0; i < n; i++)
        fn(arr[i]);
}

/* 用 typedef 简化 */
typedef int (*Comparator)(int, int);
Comparator cmp = max;

/* 返回函数指针 */
int (*getFunc(int type))(int,int) {
    return (type == 0) ? max : min;
}
05 / 数组 & 字符串
数组
/* 一维数组 */
int arr[5] = {1, 2, 3, 4, 5};
int zeros[10] = {0};   // 全0
int n = sizeof(arr) / sizeof(arr[0]);

/* 二维数组 */
int mat[3][4];
int m[2][3] = {{1,2,3},{4,5,6}};
m[1][2];              // 访问 → 6

/* VLA(C99,可变长度数组)*/
int size = 10;
int vla[size];

/* 数组传参(退化为指针)*/
void fill(int *arr, int n, int val) {
    for (int i = 0; i < n; i++)
        arr[i] = val;
}
字符串(C 风格)
#include <string.h>

char s1[] = "Hello";   // 6字节含\0
char s2[20];

/* 常用函数 */
strlen(s1)           // 5(不含\0)
strcpy(s2, s1)       // 复制字符串
strncpy(s2, s1, 10) // 安全复制
strcat(s2, " World") // 追加
strncat(s2, s1, 3)  // 安全追加
strcmp(s1, s2)       // 0=相等
strchr(s1, 'l')     // 找首个'l'
strstr(s1, "ell")   // 子串搜索
sprintf(s2, "%d", 42) // 格式化
sscanf(s1, "%s", s2)  // 解析
memset(s2, 0, sizeof(s2)) // 清零
memcpy(s2, s1, 6)     // 内存复制
06 / 指针
指针基础
int  x = 42;
int *p = &x;     // p 存储 x 的地址
*p = 100;        // 通过指针修改 x
printf("%p\n", (void*)p); // 打印地址

/* 指针算术 */
int arr[] = {10,20,30};
int *q = arr;
*(q + 1)   // 20(等价 arr[1])
q++;        // 移到下一个元素

/* 多级指针 */
int **pp = &p;
**pp = 200;

/* NULL 指针 */
int *np = NULL;
if (np != NULL) { /* 使用前检查 */ }

/* void 指针(泛型)*/
void *vp = p;
int *ip = (int*)vp; // 使用时需强转
指针 vs 数组 & const
/* 指针与数组 */
int a[] = {1,2,3};
int *p = a;      // a 退化为首元素指针
p[2] == *(p+2) == a[2]; // 都是3

/* const 与指针 */
const int *p1 = &x;  // 不能改*p1
int * const p2 = &x;  // 不能改p2
const int * const p3 = &x; // 都不能改

/* 字符串字面量(只读)*/
const char *str = "Hello"; // 推荐
char arr2[] = "Hello";     // 可修改副本

/* restrict(C99,无别名)*/
void copy(int * restrict dst,
          const int * restrict src,
          size_t n);
07 / 内存管理
动态内存分配
#include <stdlib.h>

/* malloc:分配未初始化内存 */
int *arr = (int*)malloc(10 * sizeof(int));
if (!arr) { /* 内存不足处理 */ }

/* calloc:分配并清零 */
int *arr2 = (int*)calloc(10, sizeof(int));

/* realloc:调整大小 */
arr = (int*)realloc(arr, 20 * sizeof(int));

/* free:释放内存(必须!)*/
free(arr);
arr = NULL;  // 防悬空指针
free(arr2);

/* 二维动态数组 */
int **mat = (int**)malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++)
    mat[i] = (int*)malloc(4 * sizeof(int));
/* ... 使用 mat[i][j] ... */
for (int i = 0; i < 3; i++) free(mat[i]);
free(mat);
内存区域 & 常见错误
区域内容
代码段程序指令(只读)
数据段全局/静态已初始化变量
BSS 段未初始化全局/静态变量
堆 Heapmalloc/calloc/realloc 分配
栈 Stack局部变量、函数调用帧
⚠️ 常见内存错误
• 内存泄漏:malloc 后忘记 free
• 悬空指针:free 后继续使用
• 缓冲区溢出:数组越界写入
• 重复释放:double free
• 未初始化读取:UB(未定义行为)
• 返回局部变量地址(栈帧销毁)
08 / 结构体 & 联合体 & 枚举
struct 结构体
/* 定义 */
typedef struct {
    int   id;
    char  name[50];
    float score;
} Student;

/* 创建与访问 */
Student s = {1, "Alice", 95.5f};
s.id = 2;
strcpy(s.name, "Bob");

/* 指针访问(->)*/
Student *sp = &s;
sp->score = 88.0f;  // 等价(*sp).score

/* 指定初始化(C99)*/
Student s2 = {
    .id = 3,
    .score = 100.0f,
    .name = "Carol"
};

/* 嵌套结构体 */
typedef struct {
    double x, y;
} Point;
typedef struct {
    Point center;
    double radius;
} Circle;
union & enum & 位域
/* union:共用同一内存 */
typedef union {
    int   i;
    float f;
    char  bytes[4];
} Data;
Data d; d.i = 42;
// sizeof(Data) == 4(最大成员)

/* enum 枚举 */
typedef enum {
    MON=1, TUE, WED, THU, FRI, SAT, SUN
} Weekday;
Weekday day = WED; // day == 3

/* 位域(节省空间)*/
struct Flags {
    unsigned read    : 1;
    unsigned write   : 1;
    unsigned execute : 1;
    unsigned padding : 5;
};
struct Flags f = {1, 1, 0};
链表(结构体自引用)
typedef struct Node {
    int data;
    struct Node *next;
} Node;

/* 创建节点 */
Node* newNode(int val) {
    Node *n = (Node*)malloc(sizeof(Node));
    n->data = val;
    n->next = NULL;
    return n;
}

/* 遍历 */
Node *curr = head;
while (curr != NULL) {
    printf("%d ", curr->data);
    curr = curr->next;
}

/* 释放整个链表 */
while (head) {
    Node *tmp = head->next;
    free(head);
    head = tmp;
}
09 / 文件 I/O
文件操作
#include <stdio.h>

FILE *fp = fopen("file.txt", "r");
if (!fp) { perror("fopen"); return 1; }

/* 文本读写 */
fprintf(fp, "%d %s\n", 42, "hello");
fscanf(fp, "%d %s", &n, buf);
fgets(buf, sizeof(buf), fp);    // 读一行
fputs("line\n", fp);

/* 字符级 I/O */
int ch = fgetc(fp);
fputc('A', fp);

/* 二进制读写 */
fread(&data, sizeof(data), 1, fp);
fwrite(&data, sizeof(data), 1, fp);

/* 文件定位 */
fseek(fp, 0L, SEEK_SET);  // 文件头
fseek(fp, 0L, SEEK_END);  // 文件尾
fseek(fp, 10L, SEEK_CUR); // 当前+10
long pos = ftell(fp);
rewind(fp);               // 回到文件头

fclose(fp);
文件打开模式 & printf 格式
模式说明
"r"只读(文件必须存在)
"w"只写(创建/清空)
"a"追加写
"r+"读写(文件必须存在)
"w+"读写(创建/清空)
"rb"二进制只读
"wb"二进制只写
格式符类型
%d / %iint(十进制)
%uunsigned int
%ffloat/double
%e / %g科学计数法
%cchar
%s字符串
%p指针地址
%x / %o十六/八进制
%ld / %lldlong / long long
%zusize_t
%%百分号字面量
10 / 预处理器 & 宏
预处理指令
/* 头文件包含 */
#include <stdio.h>   // 系统头文件
#include "mylib.h"   // 用户头文件

/* 宏定义 */
#define PI        3.14159265
#define MAX(a,b)  ((a)>(b)?(a):(b))
#define SQ(x)     ((x)*(x))
#define ARRAY_LEN(a) (sizeof(a)/sizeof((a)[0]))
#undef  PI         // 取消宏定义

/* 条件编译 */
#ifdef DEBUG
    printf("debug: x=%d\n", x);
#endif

#ifndef MYLIB_H
#define MYLIB_H
/* 头文件防重复包含 */
#endif

#if defined(__linux__)
#elif defined(_WIN32)
#else
#endif

/* 预定义宏 */
__FILE__  __LINE__  __DATE__
__TIME__  __func__  __STDC_VERSION__
内联函数 & _Generic(C11)
/* inline 函数(C99)*/
static inline int abs_val(int x) {
    return (x >= 0) ? x : -x;
}

/* _Generic 泛型(C11)*/
#define type_name(x) _Generic((x), \
    int:    "int",   \
    float:  "float", \
    double: "double",\
    default: "other")

/* 断言 */
#include <assert.h>
assert(ptr != NULL);          // 运行时
_Static_assert(sizeof(int)==4,
               "int must be 4 bytes"); // C11 编译时

/* 字符串化 & 连接 */
#define STRINGIFY(x) #x
#define CONCAT(a,b)  a##b
STRINGIFY(42)      // → "42"
CONCAT(foo,bar)    // → foobar
11 / 标准库速查
<stdlib.h>
/* 内存 */
malloc  calloc  realloc  free

/* 数字转换 */
atoi("42")         // → int 42
atof("3.14")       // → double
atol("100")        // → long
strtol(s, &end, 10) // 更安全
strtod(s, &end)

/* 随机数 */
srand(time(NULL));
int r = rand() % 100; // 0~99

/* 排序 & 搜索 */
qsort(arr, n, sizeof(int), cmp);
bsearch(&key, arr, n, sizeof(int), cmp);

/* 程序控制 */
exit(0);      // 正常退出
abort();      // 异常终止
atexit(cleanup); // 注册退出函数
system("ls"); // 执行系统命令
<math.h> <time.h> <ctype.h>
#include <math.h>   // 链接: -lm
sqrt(x)   pow(x,y)  fabs(x)
ceil(x)   floor(x)  round(x)
sin(x)    cos(x)    tan(x)
log(x)    log10(x)  exp(x)
M_PI  M_E  INFINITY  NAN

#include <time.h>
time_t t = time(NULL);
clock_t start = clock();
struct tm *lt = localtime(&t);
char buf[64];
strftime(buf, sizeof(buf),
         "%Y-%m-%d", lt);
double elapsed =
    (double)(clock()-start)/CLOCKS_PER_SEC;

#include <ctype.h>
isdigit(c)  isalpha(c)  isspace(c)
isupper(c)  islower(c)  isalnum(c)
toupper(c)  tolower(c)
<errno.h> & 错误处理
#include <errno.h>
#include <string.h>

/* errno 全局错误码 */
errno = 0;
FILE *fp = fopen("x.txt", "r");
if (!fp) {
    fprintf(stderr, "Error %d: %s\n",
            errno, strerror(errno));
    // 或用 perror()
    perror("fopen");
}

/* 常见 errno 值 */
ENOENT   // 文件不存在
EACCES   // 权限不足
ENOMEM   // 内存不足
EINVAL   // 无效参数
ERANGE   // 超出范围

/* setjmp / longjmp(非局部跳转)*/
#include <setjmp.h>
jmp_buf env;
if (setjmp(env) == 0) {
    /* 正常执行 */
} else {
    /* 异常处理 */
}
longjmp(env, 1); // 跳回
12 / C11 新特性 & 编译命令
C99 / C11 / C17 新特性
/* C99 */
for (int i=0; ...)  // 循环内声明
// 单行注释
bool b = true;        // <stdbool.h>
complex double z;     // <complex.h>
int arr[] = {[2]=5};  // 指定初始化
int n; scanf("%d",&n);
int vla[n];           // 变长数组

/* C11 */
_Alignas(16) int x;   // 对齐指定
_Alignof(double);     // 对齐查询
_Noreturn void die(); // 不返回
_Thread_local int tl; // 线程局部
_Atomic int counter;  // 原子类型
_Static_assert(...);  // 静态断言
_Generic(x, ...);     // 泛型选择

/* C17:主要是 C11 缺陷修复 */
GCC 编译命令
# 基本编译
gcc hello.c -o hello

# 标准指定
gcc -std=c11 -o prog prog.c
gcc -std=c99 -o prog prog.c

# 警告与调试
gcc -Wall -Wextra -Wpedantic prog.c
gcc -g prog.c    # 包含调试信息
gcc -O2 prog.c   # 优化级别2

# 链接数学库
gcc prog.c -lm -o prog

# 生成汇编
gcc -S prog.c

# 预处理输出
gcc -E prog.c

# 多文件编译
gcc main.c utils.c -o app

# 分步编译
gcc -c main.c -o main.o
gcc -c utils.c -o utils.o
gcc main.o utils.o -o app

# 宏定义
gcc -DDEBUG -DVERSION=2 prog.c
// C Language Complete Cheat Sheet  ·  C89 · C99 · C11 · C17