C 语言说明文档

举报
GrayParis 发表于 2026/08/21 10:18:30 2026/08/21
【摘要】 C 语言说明文档 1. 引言C 语言是一种通用的、过程式的编程语言,由 Dennis Ritchie 于 1972 年在贝尔实验室开发,用于重新实现 Unix 操作系统。C 语言设计简洁、高效,提供了对底层内存的精细控制,同时具备高度的可移植性。它广泛应用于系统软件、嵌入式开发、操作系统、编译器、数据库以及高性能计算等领域。C 语言是许多现代编程语言(如 C++、Java、C#、Pytho...

C 语言说明文档

1. 引言

C 语言是一种通用的、过程式的编程语言,由 Dennis Ritchie 于 1972 年在贝尔实验室开发,用于重新实现 Unix 操作系统。C 语言设计简洁、高效,提供了对底层内存的精细控制,同时具备高度的可移植性。它广泛应用于系统软件、嵌入式开发、操作系统、编译器、数据库以及高性能计算等领域。C 语言是许多现代编程语言(如 C++、Java、C#、Python 等)的基础,学习 C 语言有助于深入理解计算机的工作原理。


2. 基本语法结构

2.1 程序入口

C 程序的执行从 main 函数开始。main 函数可以定义为无参数或带参数,标准形式如下:

int main(void) {
    // 代码
    return 0;
}

或带命令行参数:

int main(int argc, char *argv[]) {
    // argc 为参数个数,argv 为参数数组
    return 0;
}

2.2 语句与块

每条语句以分号 ; 结束。使用花括号 {} 将多条语句组合成一个块(复合语句),块可以出现在任何允许单条语句的地方。

2.3 注释

  • 单行注释:// 这是单行注释
  • 多行注释:/* 这是多行注释 */(不能嵌套)

3. 数据类型

C 语言提供基本数据类型和构造类型。

3.1 基本数据类型

类型 关键字 典型大小(字节) 取值范围(以 32 位系统为例)
字符型 char 1 -128 ~ 127 或 0 ~ 255(取决于有无符号)
短整型 short 2 -32768 ~ 32767
整型 int 4 -2147483648 ~ 2147483647
长整型 long 4(Windows)或 8(Linux) 视平台而定
长长整型 long long 8 -9.22e18 ~ 9.22e18
单精度浮点型 float 4 约 ±3.4e-38 ~ ±3.4e38
双精度浮点型 double 8 约 ±1.7e-308 ~ ±1.7e308
无符号版本 unsigned 前缀(如 unsigned int 同对应类型 仅非负值,范围翻倍

3.2 派生类型

  • 数组:int arr[10];
  • 指针:int *p;
  • 结构体:struct { int a; float b; } s;
  • 联合体:union { int i; float f; } u;
  • 枚举:enum color { RED, GREEN, BLUE };

3.3 类型修饰符

  • const:定义常量,不可修改。
  • volatile:告知编译器变量可能被意外修改,禁止优化。
  • register(已过时,现代编译器自动优化):建议将变量存储在寄存器中。
  • restrict(C99):指针限定符,表示该指针是访问其指向数据的唯一方式。

4. 变量与常量

4.1 变量声明

变量需要先声明后使用,声明指定类型和名称:

int age;
float salary;
char grade;

可以在声明时初始化:

int count = 0;
double pi = 3.14159;

4.2 作用域与存储类别

  • 局部变量:在函数或块内声明,作用域限于该块。
  • 全局变量:在所有函数之外声明,作用域为整个文件(可通过 extern 跨文件使用)。
  • 静态变量:使用 static 关键字,局部静态变量保持值在函数调用间不变;全局静态变量限制其作用域为本文件。
  • 外部变量:使用 extern 声明变量在其他文件中定义。

4.3 常量

使用 const 关键字或 #define 预处理指令定义常量:

const int MAX = 100;
#define PI 3.14159

字面常量:整型(10, 0xFF)、浮点(3.14f)、字符('A')、字符串("Hello")。


5. 运算符

5.1 算术运算符

+(加)、-(减)、*(乘)、/(除)、%(取模,仅用于整数)

5.2 关系运算符

==(等于)、!=(不等于)、><>=<=,返回 1(真)或 0(假)。

5.3 逻辑运算符

&&(逻辑与)、||(逻辑或)、!(逻辑非)。短路求值。

5.4 位运算符

&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)。

5.5 赋值运算符

=+=-=*=/=%=&=|=^=<<=>>=

5.6 自增自减

++(自增)、--(自减),前缀(先变后用)和后缀(先用后变)。

5.7 条件运算符

三元运算符:条件 ? 表达式1 : 表达式2

5.8 逗号运算符

表达式1, 表达式2, ...,依次求值,结果为最后一个表达式的值。

5.9 sizeof 运算符

返回变量或类型所占字节数,结果为 size_t 类型(无符号整数)。

5.10 类型转换

  • 隐式转换:由编译器自动完成,遵循“向更高精度”的原则。
  • 显式转换(强制类型转换):(类型)表达式

6. 控制流

6.1 条件语句

  • if 语句:
if (条件) {
    // 代码
} else if (条件2) {
    // 代码
} else {
    // 代码
}
  • switch 语句:
switch (表达式) {
    case 常量1:
        // 代码
        break;
    case 常量2:
        // 代码
        break;
    default:
        // 代码
        break;
}

注意:每个 case 后通常需要 break 以避免“穿透”。

6.2 循环语句

  • while 循环:
while (条件) {
    // 代码
}
  • do-while 循环(至少执行一次):
do {
    // 代码
} while (条件);
  • for 循环:
for (初始化; 条件; 增量) {
    // 代码
}

任何部分都可以省略,但分号必须保留。

6.3 跳转语句

  • break:退出当前循环或 switch
  • continue:跳过本次循环剩余部分,进入下一轮。
  • goto:无条件跳转到标签位置(不推荐使用)。
  • return:从函数返回。

7. 函数

7.1 函数定义

返回类型 函数名(形参列表) {
    // 函数体
    return 返回值;
}

若无返回值,使用 void

7.2 函数声明(原型)

在调用函数之前,必须提供其原型,以便编译器检查参数类型和数量。原型通常放在头文件中或源文件顶部。

int add(int a, int b);

7.3 参数传递

  • 传值:将实参的副本传递给形参,函数内修改不影响原变量。
  • 传地址:通过指针传递变量的地址,函数内可通过指针修改原变量。

7.4 递归

函数可以调用自身,但必须确保有终止条件,避免无限递归。

7.5 内联函数(C99)

使用 inline 关键字建议编译器将函数展开,以减少调用开销。

7.6 函数指针

可以声明指向函数的指针,用于回调或动态调用。

int (*funcPtr)(int, int); // 指向返回int且有两个int参数的函数
funcPtr = &add;
int result = funcPtr(3, 4);

8. 数组

8.1 一维数组

声明:类型 数组名[常量表达式]; 例如:int numbers[10];
访问:下标从 0 开始,numbers[0]numbers[9]

初始化:

int a[5] = {1, 2, 3, 4, 5};
int b[] = {1, 2, 3}; // 自动确定大小
int c[5] = {0}; // 全部初始化为0

8.2 多维数组

以二维为例:int matrix[3][4]; 表示 3 行 4 列。
初始化:

int m[2][3] = {{1,2,3}, {4,5,6}};

数组名在大多数表达式中会隐式转换为指向第一个元素的指针。

8.3 字符串

C 语言没有单独的字符串类型,使用字符数组表示字符串,并以空字符 \0 结尾。

声明和初始化:

char str1[6] = "Hello"; // 实际长度6(含'\0')
char str2[] = "World";
char *str3 = "C Language"; // 字符串字面量,只读

标准库提供 <string.h> 中的字符串操作函数,如 strlenstrcpystrcatstrcmp 等。


9. 指针

9.1 指针基础

指针存储内存地址。声明:类型 *指针变量名; 例如:int *p;
取地址运算符 &:获取变量的地址。
解引用运算符 *:访问指针指向的内存。

int x = 10;
int *p = &x;
*p = 20; // 修改 x 的值为 20

9.2 指针与数组

数组名可作为指向其首元素的指针。arr[i] 等价于 *(arr + i)

9.3 指针运算

可以对指针进行加减整数运算,移动步长取决于指针指向的类型大小。

9.4 指向指针的指针

int **pp; 用于多级间接访问。

9.5 空指针与野指针

  • 空指针:指向地址 0 的指针,通常用 NULL(void*)0 表示,表示不指向任何有效对象。
  • 野指针:未初始化或指向已释放内存的指针,访问可能导致未定义行为。

9.6 const 与指针

  • const int *p;:指向常量的指针(所指内容不可变,指针可变)。
  • int * const p;:常量指针(指针本身不可变,所指内容可变)。
  • const int * const p;:两者都不可变。

9.7 void 指针

void * 可以指向任意类型的数据,但解引用前必须先强制转换为具体类型。常用于通用内存操作(如 malloc)。


10. 结构体与联合体

10.1 结构体

结构体将不同类型的数据组合成一个整体。

定义:

struct Student {
    char name[50];
    int age;
    float score;
};

声明结构体变量:

struct Student s1;
struct Student s2 = {"Alice", 20, 85.5};

访问成员:. 运算符,如 s1.age

指向结构体的指针:使用 -> 访问成员,如 p->age

10.2 类型定义(typedef)

使用 typedef 为类型起别名,简化书写:

typedef struct Student Student;
Student s3;
// 或直接定义
typedef struct {
    int x;
    int y;
} Point;
Point p1;

10.3 结构体内存对齐

编译器可能在结构体成员之间插入填充字节,以提高访问效率。可以使用 #pragma pack__attribute__((packed)) 调整对齐。

10.4 联合体

联合体允许在同一内存位置存储不同类型的数据,但同一时刻只能使用其中一种成员。大小取决于最大成员的大小。

union Data {
    int i;
    float f;
    char str[20];
};

10.5 枚举

enum 定义一组命名的整型常量,默认从 0 递增。

enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
enum Weekday today = WED;

11. 动态内存管理

C 标准库 <stdlib.h> 提供四个函数用于动态内存管理:

  • void *malloc(size_t size):分配大小为 size 字节的连续内存,初始值不确定。若分配失败返回 NULL
  • void *calloc(size_t num, size_t size):分配 num 个大小为 size 字节的元素,并将内存初始化为 0。
  • void *realloc(void *ptr, size_t new_size):重新调整之前分配的内存块大小,可能移动数据。若 ptrNULL,则等同于 malloc
  • void free(void *ptr):释放之前分配的内存,避免内存泄漏。释放后指针应置为 NULL

示例:

int *arr = (int*)malloc(10 * sizeof(int));
if (arr == NULL) { /* 处理错误 */ }
// 使用 arr...
free(arr);
arr = NULL;

12. 文件输入输出

C 标准库 <stdio.h> 提供了文件操作函数。文件操作流程:打开文件 → 读写操作 → 关闭文件。

12.1 文件指针

使用 FILE * 类型表示文件流。

12.2 打开与关闭

  • FILE *fopen(const char *filename, const char *mode);
    模式包括:
    • "r":只读,文件必须存在。
    • "w":只写,若存在则清空,不存在则创建。
    • "a":追加,若不存在则创建。
    • "r+":读写,文件必须存在。
    • "w+":读写,若存在则清空,不存在则创建。
    • "a+":读写,追加模式。
      二进制模式加 b,如 "rb"
  • int fclose(FILE *stream);:关闭文件。

12.3 读写操作

  • 字符级:fgetcfputcungetc
  • 字符串级:fgets(读取一行,带换行符)、fputs
  • 格式化:fprintffscanf
  • 二进制块:freadfwrite

示例:

FILE *fp = fopen("data.txt", "r");
if (fp == NULL) { perror("打开失败"); return; }
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
    printf("%s", buffer);
}
fclose(fp);

12.4 文件定位

  • fseek(FILE *stream, long offset, int whence); whence 为 SEEK_SETSEEK_CURSEEK_END
  • ftell(FILE *stream); 返回当前文件位置。
  • rewind(FILE *stream); 回到文件开头。
  • feof(FILE *stream); 检查是否到达文件末尾。

13. 预处理器

预处理器在编译之前处理以 # 开头的指令。

13.1 宏定义

#define 定义宏,可以是常量或带参数的宏。

#define PI 3.14159
#define SQUARE(x) ((x)*(x)) // 注意括号

带参数的宏需谨慎使用,避免副作用。

13.2 条件编译

根据条件包含或排除代码块。

#ifdef DEBUG
    printf("调试信息\n");
#endif

#ifndef HEADER_H
#define HEADER_H
// 头文件保护
#endif

#if defined(WIN32)
    // Windows 特定代码
#elif defined(LINUX)
    // Linux 特定代码
#else
    // 其他
#endif

13.3 文件包含

#include <filename> 搜索系统头文件路径;#include "filename" 先搜索当前目录,再搜索系统路径。

13.4 其他指令

  • #undef:取消宏定义。
  • #error:产生编译错误消息。
  • #pragma:编译器特定指令(如 #pragma once)。

13.5 预定义宏

  • __LINE__:当前行号。
  • __FILE__:当前文件名。
  • __DATE__:编译日期。
  • __TIME__:编译时间。
  • __STDC__:若编译器符合 ANSI C,则定义为 1。

14. 标准库概述

C 标准库提供了丰富的函数,通过包含相应头文件使用。主要头文件及功能:

  • <stdio.h>:输入输出(printfscanf、文件操作等)。
  • <stdlib.h>:通用工具(内存分配、转换、随机数、退出等)。
  • <string.h>:字符串处理(复制、连接、比较、查找等)。
  • <math.h>:数学函数(sincossqrtpow 等)。
  • <time.h>:时间和日期(timeclockdifftime 等)。
  • <ctype.h>:字符分类(isalphaisdigittoupper 等)。
  • <stdbool.h>(C99):布尔类型 booltrue/false
  • <stdint.h>(C99):精确宽度整数类型(如 int32_t)。
  • <limits.h>:基本类型的取值范围(如 INT_MAX)。
  • <float.h>:浮点数属性(如 FLT_MAX)。
  • <assert.h>:断言 assert,用于调试。
  • <errno.h>:错误码定义,配合 perrorstrerror 使用。

15. 常见编程实践与最佳建议

  • 初始化变量:声明时尽量初始化,避免使用未初始化的值。
  • 检查返回值:特别是 mallocfopen 等可能失败的函数,务必检查返回值。
  • 防止内存泄漏:动态分配的内存必须用 free 释放,并确保所有路径都释放。
  • 数组边界检查:C 不检查数组越界,程序员需确保索引不超出范围。
  • 指针安全:使用前确保指针非空,且指向有效内存;释放后置为 NULL
  • 使用 const 修饰不修改的参数:提高代码可读性和安全性。
  • 函数设计:函数应单一职责,长度适中,参数不宜过多。
  • 头文件保护:使用 #ifndef / #define#pragma once 避免重复包含。
  • 可移植性:避免依赖特定平台的大小端、字节对齐或类型大小,使用 sizeof 和标准类型(如 int32_t)。
  • 注释与文档:为复杂逻辑和公开接口编写注释,便于维护。
  • 编译选项:开启编译器警告(如 -Wall -Wextra),并认真对待警告。
  • 代码风格:保持一致缩进、命名规范(如 snake_case 或 camelCase),提高团队协作效率。

16. 结语

C 语言是一门强大而简洁的编程语言,它赋予程序员对底层内存和硬件的直接控制,同时也要求程序员具备严谨的内存管理和错误处理意识。掌握 C 语言不仅有助于编写高性能的程序,更能为理解操作系统、编译原理和计算机体系结构打下坚实基础。通过不断实践、阅读优秀代码和深入理解语言特性,您将能够熟练运用 C 语言解决各种实际问题。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。