// C89 · C99 · C11 · C17 标准全覆盖
#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;
}
| 类型 | 大小 | 范围 / 说明 |
|---|---|---|
| char | 1 B | -128 ~ 127 |
| unsigned char | 1 B | 0 ~ 255 |
| short | 2 B | -32768 ~ 32767 |
| int | 4 B | -2³¹ ~ 2³¹-1 |
| long | 4/8 B | 平台相关 |
| long long | 8 B | -2⁶³ ~ 2⁶³-1 |
| float | 4 B | ~7 位有效数字 |
| double | 8 B | ~15 位有效数字 |
| long double | 8/16 B | 扩展精度 |
| _Bool (bool) | 1 B | 0 或 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;
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 最低 | ,(逗号) |
/* 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: ;
/* 函数原型 */
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;
}
/* 一维数组 */
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;
}
#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) // 内存复制
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; // 使用时需强转
/* 指针与数组 */
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);
#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 段 | 未初始化全局/静态变量 |
| 堆 Heap | malloc/calloc/realloc 分配 |
| 栈 Stack | 局部变量、函数调用帧 |
/* 定义 */
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:共用同一内存 */
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;
}
#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);
| 模式 | 说明 |
|---|---|
| "r" | 只读(文件必须存在) |
| "w" | 只写(创建/清空) |
| "a" | 追加写 |
| "r+" | 读写(文件必须存在) |
| "w+" | 读写(创建/清空) |
| "rb" | 二进制只读 |
| "wb" | 二进制只写 |
| 格式符 | 类型 |
|---|---|
| %d / %i | int(十进制) |
| %u | unsigned int |
| %f | float/double |
| %e / %g | 科学计数法 |
| %c | char |
| %s | 字符串 |
| %p | 指针地址 |
| %x / %o | 十六/八进制 |
| %ld / %lld | long / long long |
| %zu | size_t |
| %% | 百分号字面量 |
/* 头文件包含 */
#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__
/* 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
/* 内存 */
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"); // 执行系统命令
#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)
#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); // 跳回
/* 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 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