菜鸟教程 -- 学的不仅是技术,更是梦想!

C 教程
(追記) (追記ここまで)

C 基础语法

C 语言是一种通用的编程语言,广泛应用于系统编程、嵌入式开发和高性能计算等领域。

C 语言具有高效、灵活、可移植性强等特点,是许多其他编程语言(如 C++、Java、Go)的基础,至今仍是操作系统、驱动程序和底层库开发的主流选择。

在 C 语言中,令牌(Token)是程序的基本组成单位,编译器通过对源代码进行词法分析,将代码分解成一个个的令牌。令牌是编译器能识别的最小有意义单元,整个 C 程序都由这些令牌构成。

C 语言的令牌主要包括以下几种类型:

  • 关键字(Keywords):语言预留的具有特殊含义的单词,如 intifreturn
  • 标识符(Identifiers):程序员自定义的名称,用于变量、函数、数组等。
  • 常量(Constants):程序中固定不变的值,如整数 42、浮点数 3.14
  • 字符串字面量(String Literals):由双引号括起来的字符序列,如 "Hello"
  • 运算符(Operators):用于执行运算的符号,如 +==&&
  • 分隔符(Separators):用于分隔语句和代码块的符号,如 ;{}

C 程序的基本结构

这是一个简单的 C 语言程序,可以输出 "Hello, World!":

实例

#include <stdio.h>

int main() {
printf("Hello, World!\n");
return 0;
}

以上代码组成结构如下:

  • 预处理器指令:如 #include#define,在编译前由预处理器处理。
  • 主函数:每个 C 程序都有且只有一个 main() 函数,是程序的执行入口。
  • 变量声明:声明程序中使用的变量,C89 要求声明必须在代码块最开头。
  • 函数定义:定义程序中使用的函数,描述函数的具体实现逻辑。

更复杂一点的 C 程序结构说明(后面章节会对每个知识点展开说明):

实例

#include <stdio.h> // 头文件包含

#define PI 3.14159 // 宏定义

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

int main() { // 主函数
// 变量声明
int num1, num2, sum;

// 用户输入
printf("Enter two integers: ");
scanf("%d %d", &num1, &num2);

// 函数调用
sum = add(num1, num2);

// 输出结果
printf("Sum: %d\n", sum);

return 0; // 返回 0 表示程序成功执行
}

// 函数定义
int add(int a, int b) {
return a + b;
}

头文件包含

  • 头文件通常在程序的开头使用 #include 指令包含。头文件提供了函数和库的声明,如标准输入输出库 <stdio.h>、标准库 <stdlib.h> 等。它们定义了函数、宏、常量等使程序能够使用预定义的库函数。
  • 系统头文件使用尖括号 <>,自定义头文件使用双引号 "",两者的搜索路径不同。
  • 示例:#include <stdio.h>(系统头文件)、#include "myheader.h"(自定义头文件)

宏定义

  • 宏是通过 #define 指令定义的符号常量或代码片段。宏在编译前由预处理器进行文本替换,不占用运行时内存,常用于定义常量或简单的内联代码逻辑。
  • 宏没有类型检查,使用时需谨慎;对于有类型要求的常量,推荐使用 const 变量替代。
  • 示例:#define PI 3.14159#define MAX(a, b) ((a)> (b) ? (a) : (b))

函数声明

  • 在 C 语言中,函数的声明(也称原型)必须在函数定义或调用之前出现。声明提供了函数的返回类型、函数名和参数列表,以便编译器在调用点进行类型检查。
  • 函数声明可以放在头文件中,供多个源文件共享使用。
  • 示例:int add(int a, int b);

主函数

  • main() 函数是 C 程序的入口点,每个 C 程序都必须包含一个 main() 函数。程序从 main() 开始执行,返回值通常为 0 表示程序成功执行,非零值表示出现了错误。
  • main() 函数也可以接收命令行参数:int main(int argc, char *argv[]),其中 argc 是参数个数,argv 是参数字符串数组。
  • 示例:int main() { ... }

变量声明

  • 在 C 程序中,所有变量必须在使用前声明其类型。变量可以在 main() 函数中声明(局部变量),也可以在函数外部全局声明(全局变量)。
  • 声明变量时可同时进行初始化,未初始化的局部变量包含不确定值(垃圾值),而全局变量和静态变量会被自动初始化为 0
  • 示例:int count = 0;float price = 9.99;char grade = 'A';

语句和表达式

  • 语句是 C 程序的基本执行单元,通常是函数调用、赋值、控制语句(如 iffor 等)或表达式。表达式是由变量、操作符和常量组成的代码片段,能够计算出一个值。
  • C 语言中,赋值本身也是一个表达式,具有值(即被赋的值),因此可以写出 a = b = c = 0; 这样的链式赋值。
  • 示例:
    printf("Enter two integers: ");
    sum = add(num1, num2);

控制流语句

  • 控制流语句用于控制程序执行的顺序,包括条件判断(if/elseswitch)和循环(forwhiledo-while)。还有跳转语句 breakcontinuegotoreturn
  • 合理使用控制流语句是写出逻辑清晰程序的关键,应避免滥用 goto 以保持代码可读性。
  • 示例:
    if (num1 > num2) {
     printf("num1 is greater than num2");
    }

函数定义

  • 函数定义包含完整的函数体,描述了函数的具体实现。一个函数由返回类型、函数名、参数列表和函数体组成。良好的函数设计应遵循"单一职责"原则,每个函数只做一件事。
  • C 语言的函数不支持重载,每个函数名在同一作用域中必须唯一。函数可以递归调用自身。
  • 示例:
    int add(int a, int b) {
     return a + b;
    }

返回语句

  • return 语句用于终止函数的执行,并将控制权连同返回值一起交还给调用者。void 类型的函数可以使用不带值的 return; 提前退出,也可以省略 return 语句。
  • main() 函数的返回值会传递给操作系统,0 通常表示成功,可使用标准宏 EXIT_SUCCESSEXIT_FAILURE(定义在 <stdlib.h>)。
  • 示例:return 0;return EXIT_SUCCESS;

分隔符

分隔符用于分隔语句、表达式和代码块,帮助编译器理解程序的结构,常见的分隔符包括:

  • 逗号 ,:用于分隔变量声明、函数参数或初始化列表中的多个元素。
  • 分号 ;:用于结束一条语句,是 C 语言中最常见的分隔符。
  • 括号:
    • 圆括号 ():用于函数调用的参数列表、控制流语句的条件,以及强制表达式求值顺序。
    • 花括号 {}:用于定义函数体、控制流代码块,以及复合字面量与数组/结构体的初始化。
    • 方括号 []:用于数组的声明和元素访问(下标运算)。

在 C 程序中,分号 ; 是语句结束符,每个语句必须以分号结束,它表明一个逻辑实体的结束。缺少分号是初学者最常见的语法错误之一。

例如,下面是两个不同的语句:

printf("Hello, World! \n");
return 0;

一个单独的分号也可以作为一个空语句,表示什么都不做,常用于某些循环结构中:

while (condition); // 空循环体,等待条件变化

注释

C 语言有两种注释方式:

// 单行注释

// 开始的单行注释(C99 引入),这种注释从 // 起到行尾结束,可以单独占一行,也可以放在代码行的末尾。

/* 单行注释 */
/* 
 多行注释
 多行注释
 多行注释
 */

/* */ 这种格式的注释可以单行或多行,适合用于函数说明、模块头部等较长的注释场景。

实例

// 这是单行注释

/*
这是多行注释
它可以跨越多行
*/


int main() {
// 打印一条消息
printf("Hello, World!\n");
return 0;
}

使用注释时需注意以下几点:

  • 不能在注释内嵌套注释(/* /* */ */ 是非法的)。
  • 注释不能出现在字符串字面量或字符常量内部。
  • 注释是写给人看的,应简洁明了,重点解释"为什么"而非"做了什么",代码本身应该能表达"做什么"。
  • 良好的注释习惯是专业编程的重要组成部分,有助于代码维护和团队协作。

标识符

标识符是程序中变量、函数、数组、类型等的名字,由程序员自行定义。标识符由字母(大写或小写)、数字和下划线组成,但第一个字符必须是字母或下划线,不能是数字。

一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。

C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。因此,在 C 中,Manpowermanpower 是两个不同的标识符。下面列出几个有效的标识符:

mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal

以下是一些无效的标识符示例及原因:

2abc // 错误:以数字开头
my-name // 错误:包含连字符 -
float // 错误:与关键字重名
my name // 错误:包含空格

命名建议:标识符应具有描述性,能清晰表达其用途。常见的命名风格有下划线命名法(my_variable)和小驼峰命名法(myVariable),在同一项目中保持一致即可。以双下划线 __ 开头的标识符通常由编译器或标准库保留,应避免在用户代码中使用。

常量

常量是固定值,在程序执行期间不会改变。C 语言中定义常量主要有两种方式:使用 const 关键字或使用 #define 宏定义。

常量可以是整型常量、浮点型常量、字符常量、枚举常量等:

const int MAX = 100; // 整型常量
const float PI = 3.14159; // 浮点型常量
const char NEWLINE = '\n'; // 字符常量(转义字符)

字符常量中常用的转义字符包括:

  • '\n':换行
  • '\t':水平制表符
  • '\\':反斜杠
  • '\'':单引号
  • '0円':空字符(字符串结束标志)

使用 const 定义的常量有类型信息,编译器可以进行类型检查,相比 #define 宏更安全,是 C99 及之后推荐的方式。

字符串字面量

字符串字面量是由双引号括起来的字符序列,用于表示文本数据。

字符串字面量在内存中以字符数组的形式存储,末尾会自动添加一个空字符 0円(即 null 终止符),标志字符串的结束。

char greeting[] = "Hello, World!"; // 编译器自动计算长度(包含 0円)

以下是关于字符串字面量的几点重要说明:

  • "Hello" 在内存中实际占 6 个字节:'H'、'e'、'l'、'l'、'o'、'0円'
  • 字符串字面量存储在只读内存区域,不可修改;若需修改,应将其复制到字符数组中。
  • 两个相邻的字符串字面量会被编译器自动拼接:"Hello, " "World!" 等同于 "Hello, World!"
  • 字符 'A'(字符常量)和字符串 "A"(字符串字面量)是不同的,后者包含 'A''0円' 两个字符。

运算符(Operators)

运算符用于执行各种操作,如算术运算、逻辑运算、比较运算等。运算符作用于操作数,形成表达式并产生结果。

C 语言中的运算符种类繁多,常见的包括:

  • 算术运算符:+, -, *, /, %(其中 / 对整数做整除,% 取余数)
  • 关系运算符:==, !=, >, <, >=, <=(返回 1 表示真,0 表示假)
  • 逻辑运算符:&&(与), ||(或), !(非),支持短路求值
  • 位运算符:&(按位与), |(按位或), ^(按位异或), ~(按位取反), <<(左移), >>(右移)
  • 赋值运算符:=, +=, -=, *=, /=, %=(复合赋值,如 a += b 等价于 a = a + b)
  • 自增/自减运算符:++(自增), --(自减),分前缀(先运算再取值)和后缀(先取值再运算)两种形式
  • 其他运算符:sizeof(计算类型或变量字节大小), ?:(三目运算符), &(取地址), *(解引用), ->(指针访问成员), .(直接访问成员)
int a = 5, b = 10;
int sum = a + b; // 算术运算符 +,sum = 15
int isEqual = (a == b); // 关系运算符 ==,isEqual = 0(假)
int result = a &lt;&lt; 1; // 位运算左移,result = 10(相当于 a * 2)
a++; // 后缀自增,a 变为 6
int max = (a > b) ? a : b; // 三目运算符,max = b = 10

运算符具有优先级和结合性:优先级决定运算顺序,结合性决定同级运算符的运算方向。当不确定优先级时,建议使用圆括号明确分组,以提高代码可读性。

关键字

下表列出了 C 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称,它们在 C 语言中具有特定的语法含义。

关键字 说明
auto声明自动变量(局部变量默认存储类型,现代 C 中很少显式使用)
break跳出当前循环或 switch 语句
caseswitch 语句中的分支标签
char声明字符型变量或函数返回值类型(通常占 1 字节)
const定义只读常量,被 const 修饰的变量其值不能再被改变
continue结束本次循环迭代,直接开始下一轮循环
defaultswitch 语句中的默认分支(所有 case 均不匹配时执行)
dodo-while 循环的循环体,循环体至少执行一次
double声明双精度浮点型变量或函数返回值类型(通常占 8 字节)
else条件语句的否定分支(与 if 连用)
enum声明枚举类型,用于定义一组命名的整型常量
extern声明变量或函数在其它文件或本文件的其他位置定义
float声明单精度浮点型变量或函数返回值类型(通常占 4 字节)
forfor 循环语句,适合已知循环次数的场景
goto无条件跳转语句(应谨慎使用,可能降低代码可读性)
if条件判断语句
int声明整型变量或函数返回值类型(通常占 4 字节)
long声明长整型变量或函数返回值类型
register建议编译器将变量存入寄存器以提高访问速度(现代编译器通常自动优化)
return函数返回语句,可带返回值,也可不带(void 函数)
short声明短整型变量或函数返回值类型(通常占 2 字节)
signed声明有符号类型变量(可表示负数,整型默认有符号)
sizeof计算数据类型或变量所占的字节数(编译期运算符)
static声明静态变量(局部静态变量生命周期延续到程序结束;全局静态变量限制为文件作用域)
struct声明结构体类型,将不同类型的数据组合成一个整体
switch多分支选择语句,根据表达式的值跳转到对应 case
typedef为已有数据类型定义新的别名,提高代码可读性
unsigned声明无符号类型变量(只能表示非负数,范围更大)
union声明共用体类型,所有成员共享同一块内存空间
void声明函数无返回值或无参数;也用于声明无类型指针 void*
volatile声明变量可能被程序外部因素(如硬件或中断)改变,禁止编译器优化该变量的读写
whilewhile 循环语句,适合循环次数未知但终止条件明确的场景

C99 新增关键字

_Bool _Complex _Imaginary inline restrict

C99 新增的关键字主要用于:布尔类型支持(_Bool)、复数支持(_Complex_Imaginary)、内联函数优化(inline)、指针别名限制优化(restrict)。

C11 新增关键字

_Alignas _Alignof _Atomic _Generic _Noreturn
_Static_assert _Thread_local

C11 新增的关键字主要用于:内存对齐控制(_Alignas_Alignof)、原子操作与多线程支持(_Atomic_Thread_local)、泛型选择(_Generic)、静态断言(_Static_assert)和标记无返回值函数(_Noreturn)。


C 中的空格

只包含空格的行,被称为空白行,可能带有注释,C 编译器会完全忽略它。

在 C 中,空格用于描述空白符(空格键)、制表符(Tab)、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,下一个元素在哪里开始。因此,在下面的语句中:

int age;

intage 之间必须至少有一个空格字符(通常是一个空白符),这样编译器才能够区分它们。另一方面,在下面的语句中:

fruit = apples + oranges; // 获取水果的总数

fruit=,或者 =apples 之间的空格字符不是必需的,但是为了增强可读性,您可以根据需要适当增加一些空格。

良好的空格和缩进习惯是高质量代码的重要组成部分,建议遵循以下规范:

  • 使用一致的缩进(通常是 4 个空格或 1 个制表符)来表示代码块层级。
  • 在运算符两侧添加空格(如 a + b),使表达式更易读。
  • 在逗号后添加空格(如 int a, b, c;),区分多个元素。
  • 适当使用空行分隔逻辑相关的代码段,提高整体可读性。
AI 思考中...

4 篇笔记 写笔记

  1. #0

    终究被人遗忘

    221***[email protected]

    415

    C关键字:

    按年份起始:

    • auto break case char const continue default do
    • double else enum extern float for goto if
    • int long register return short signed sizeof static
    • struct switch typedef union unsigned void volatile while

    1999年12月16日,ISO推出了C99标准,该标准新增了5个C语言关键字:

    • inline restrict _Bool _Complex _Imaginary

    2011年12月8日,ISO发布C语言的新标准C11,该标准新增了7个C语言关键字:

    • _Alignas _Alignof _Atomic _Static_assert _Noreturn _Thread_local _Generic

    终究被人遗忘

    221***[email protected]

    9年前 (2017年07月15日)
  2. #0

    Justfotoy

    104***[email protected]

    429

    1、C语言的程序构成方式

    • 1)c语言程序由函数构成,每个函数可以实现一个或多个功能。
    • 2)一个正规程序可以有多个函数,但是有且只有一个主函数。
    • 3)函数只有在被调用的时候才执行,主函数由系统调用执行。
    • 4)函数的格式必须按照规范书写。
    • 5)C 语言程序文件的后缀为 .c

    2、一个简单的C程序

    在 Mac OS 系统上可以使用Xcode中创建 c 语言程序,打开 Xcode -- 点击 create a new xcode project -- 点击 os X-- 右边选择 commad line tool -- next -- product name 填项目名称,organization name 填公司名称,organization identifier 填公司网址的倒序。language选择 C。

    简单打印一句话。

    #include <stdio.h>
    int main(int argc, const char * argv[]) {
     printf("Hello, World!\n");
     return 0;
    }

    Justfotoy

    104***[email protected]

    9年前 (2017年09月01日)
  3. #0

    呆呆1020

    180***[email protected]

    267

    关键字

    关键字:C语言的关键字,是C语言保留的一些有特殊作用词语。一共有32个关键字,

    关键字说明:

    关键字描述
    auto 声明自动变量
    double 声明双精度变量或函数
    typedef用以给数据类型取别名
    register声明寄存器变量
    short声明短整型变量或函数
    char声明字符型变量或函数
    const声明只读变量
    static声明静态变量int声明整型变量或函数
    struct 声明结构体变量或函数
    unsigned声明无符号类型变量或函数
    volatile说明变量在程序执行中可被隐含地改变long声明长整型变量或函数
    union声明共用数据类型
    signed声明有符号类型变量或函数
    void声明函数无返回值或无参数,声明无类型指针float声明浮点型变量或函数
    enum声明枚举类型
    extern声明变量是在其他文件正声明
    if条件语句
    else条件语句否定分支(与 if 连用)
    switch用于开关语句
    case开关语句分支
    for一种循环语句do循环语句的循环体
    while循环语句的循环条件
    goto无条件跳转语句
    continue结束当前循环,开始下一轮循环break跳出当前循环
    default开关语句中的"其他"分支
    sizeof计算数据类型长度
    return子程序返回语句(可以带参数,也可不带参数)循环条件

    标识符

    标识符:在编程语言中,标识符是用户编程时使用的名字,变量、常量、函数、语句块都有名字。是用来标识某个实体的一个符号,是对变量名、函数名、标号和其他各种用户定义的对象命名。

    C语言中标识符的命名规范:

    • 1.标识符由字母、数字、下划线组成,并且首字母不能是数字。
    • 2.不能把C的关键字作为用户的标识符,例如:if、for、while等。(注:标识符不能和C语言的关键字相同,也不能和用户自定义的函数或C语言库函数同名)
    • 3.标识符长度是由机器上的编译系统决定的,一般的限制为8字符,(注:8字符长度限制是C89标准,C99标准已经扩充长度,其实大部分工业标准都更长)。
    • 4.标识符对大小写敏感,即严格区分大小写。一般对变量名用小写,符号常量命名用大写。(注:C语言中字母是区分大小写的,因此score、Score、SCORE分别代表三个不同的标识符)
    • 5.标识符命名应做到"见名知意",例如,长度(外语:length),求和、总计(外语:sum),圆周率(外语:pi)
    呆呆1020

    呆呆1020

    180***[email protected]

    9年前 (2017年12月15日)
  4. #0

    CSTwang

    248***[email protected]

    152

    C 语言有两种注释方式:

    • (1)以 // 开始的单行注释,这种注释可以单独占一行,也可以出现在一行中其他内容的右侧,注意这种注释不能跨行。若注释内容一行内写不下可以在下一行重新用 // ,继续写注释。
    • (2)以 /* 开始,以 */ 结束的块式注释。这种注释可以包含多行内容。编译系统在发现一个 /* 后,会开始找注释结束符 */,把两者间的内容作为注释。

    应注意的是在字符串中的和都不作为注释的开始。而是作为字符串的一部分。如:

    printf("//how do you do!\n");
    或
    printf("/*how do you do!*/\n");

    输出分别是://how do you do!/*how do you do!*/

    CSTwang

    248***[email protected]

    8年前 (2018年08月02日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /