C语言入门12个核心概念-新手避坑指南

自学C语言别死磕!12个核心概念,搞懂少踩80%新手坑

网上的C语言入门教程有个通病:只教你怎么写,不告诉你为什么会崩。抄完代码运行一看——乱码、崩溃、编译器甩一堆看不懂的英文,你开始怀疑自己是不是不适合学编程。

其实不是。绝大多数新手bug,根源就那十几个基础概念没搞透。0、'0'、\0 分不清,字符串哪段能改哪段不能改不知道,if后面多写个分号找了两小时——这些才是真凶。

这篇把入门阶段最容易踩坑的12个概念掰开揉碎讲,末尾附编译错误对照表和printf格式符速查。建议先收藏,写代码遇到报错回来翻,基本都能对上号。

目录

C语言是什么?

main函数

printf和库函数

关键字与标识符

字符

ASCII编码

字符串(乱码崩溃重灾区)

\0结束符

转义字符

语句

语句分类

代码注释

附录

1. C语言是什么?

1972年,丹尼斯·里奇在贝尔实验室搞出了C语言,初衷是用它重写Unix操作系统。这门语言牛逼的地方在于:写起来像高级语言一样能读,跑起来又贴近硬件够快。所以几十年过去了,底层开发还在用它,编程入门也还在教它。

说人话就是:计算机只认二进制的0和1,你说中文它听不懂,所以需要一门编程语言当中介。C语言就是众多中介里的一个,跟Python、Java、Go干的是同一类活。

唯一要注意的:C是编译型语言,你写的 .c 文件不能直接跑,得先用编译器翻译成机器指令,生成可执行文件才能运行。新手最开始容易在这一步懵——写完代码点运行没反应,大概率是编译没通过,不是代码没保存。

2. main函数

main 就是程序的入口。操作系统启动你的程序之后,从 main 函数的第一行开始往下执行,就这么简单。

有且只有一个规矩:能直接运行的程序,有且只能有一个main函数。 写两个就报 redefinition of 'main',这个后面错误对照表里会提到。

库项目(只给别人提供功能、自己不跑的代码)不需要main,但初学阶段你碰不到这个,记住"一个程序一个main"就够了。

关于 return 0;:C99标准允许main函数末尾不写return,编译器会自动帮你补。但只有main有这个待遇,你自己写的函数该return还是得return。新手建议老老实实写上,养成习惯没坏处。

最小可运行程序长这样,以后写任何代码都可以从这个骨架往上加:

#include

int main(void)

{

printf("hello, world\n");

return 0;

}

3. printf和库函数

你不用自己写怎么在屏幕上打印文字,C标准库已经帮你写好了,printf 就是其中一个工具。这种"标准预先实现好、你直接调用"的函数,叫库函数。

用 printf 之前必须写 #include 。这行代码的意思是:把标准输入输出库的"说明书"引进来。头文件里只有函数声明(叫什么、收什么参数),真正干活的代码在系统库里。不写这行,编译器不认识printf,直接报错。

别搞混:#include 既不是函数也不是头文件,它是预处理指令——在编译之前先执行的一道命令。

4. 关键字与标识符

关键字

C语言自带的、意思固定死的词,叫关键字。int、if、while、return、char、for、else 这些都是。

三条铁律:

不能拿来当变量名或函数名,硬用就编译报错

你改不了它的意思,编译器底层直接解析

全是小写,没有大写的关键字

注意:printf 不是关键字,它是库函数。关键字是语言本身的词汇,库函数是别人写好的工具,两码事。

标识符(命名规则)

你自己给变量、函数起的名字叫标识符。规则很简单,但新手天天在这翻车:

只能用字母、数字、下划线

不能数字开头——2name 非法,name2 合法

区分大小写——Age 和 age 是两个东西

不能跟关键字重名

合法

非法

原因

age

2num

数字开头

student_name

my-name

含减号

_count

int

关键字

num2

我的变量

含中文

写中文变量名、变量名里带空格、不小心用了关键字——这三种情况占了新手编译错误的半壁江山。

5. 字符

单个符号就是字符。字母、数字、标点、空格,都算。

C语言里用单引号包一个字符:'A'、'5'、' '(空格也是字符)。类型是 char,占1个字节。

单引号里只能放一个字符。放两个?语法错误,编译器不跟你客气。

6. ASCII编码

计算机存的是数字,不是字母。那怎么表示'A'?靠一张约定好的映射表——ASCII编码,给每个常用符号分配一个整数编号。

三个必须背下来的数:

字符

ASCII值

'A'

65

'a'

97

'0'

48

标准ASCII一共128个编号(0~127):

0~31 是控制字符,看不见,用来干换行、制表这种事。10号是换行 \n,9号是制表符 \t

32~126 是能打印出来的,空格、数字、大小写字母、英文标点都在这

两个容易忽略的点:

ASCII里没有中文。中文靠UTF-8、GBK这些编码,一个汉字通常占好几个字节

有些编译器里 char 默认是有符号的,范围-128~127。你往char里塞个大于127的数,结果可能跟你想的不一样

7. 字符串(乱码崩溃重灾区)

这一节是新手翻车最密集的区域,打起精神。

C语言没有专门的字符串类型,字符串本质就是char类型的数组。用双引号包起来:"hello"、"abc"。

编译器会在双引号字符串的末尾自动加一个你看不见的 \0,作为结束标记。\0 占1个字节,但不会打印出来。

所以 "abc" 在内存里实际是:'a' 'b' 'c' '\0',4个字节,不是3个。

'A' 和 "A" 完全不是一回事

写法

类型

内存里存的

占几个字节

'A'

char字符

'A'

1

"A"

字符串

'A' + '\0'

2

单引号一个字符,双引号是字符串末尾还藏个 \0,这个区别搞不清,后面全是坑。

三个最容易犯的错

双引号字符串别手动加 \0——编译器已经帮你加了,你再写一个就是两个结束标记,虽然不一定崩,但纯属多余

自己用char数组拼字符串,必须手动加 \0——不加的话,printf("%s") 会一直往后读内存,直到碰巧读到一个0为止,中间全是垃圾数据,屏幕上就是一堆乱码

字符串里可以写转义字符,"hello\nworld" 里的 \n 算一个字符,不是两个

很多教程不会告诉你的坑

双引号直接写出来的字符串字面量,存在只读内存段里。意思就是:程序运行的时候你不能改它,硬改直接崩溃(段错误)。

别问我怎么知道的,问就是新手期写过 char *s = "test"; s[0] = 'T'; 然后调了半小时bug。

需要能改的字符串?用字符数组:

#include

int main(void)

{

char buf[] = "test"; // 字符数组,内容可以改

buf[0] = 'T';

printf("%s\n", buf); // 输出 Test

return 0;

}

8. \0结束符

\0 是一个转义字符,ASCII编号是0,专门用来标记字符串的结束。

三条规则:

双引号写的字符串,编译器自动补 \0

自己拿char数组拼字符串,得自己写 \0

\0 不显示,但占1个字节

0、'0'、\0 是三个完全不同的东西

写法

是什么

ASCII值

能打印吗

\0

字符串结束标记(转义字符)

0

不能

0

int类型的数字0

能(打印数字0)

'0'

字符0

48

能(打印字符0)

做字符判断的时候特别容易搞混——比如你想判断一个字符是不是数字0,得写 if(c == '0'),写 if(c == 0) 判断的是字符串结束符,完全两码事。

9. 转义字符

有些符号没法直接写在引号里,比如你想在字符串里打个双引号,写 "他说"你好"" 编译器直接懵了——它不知道哪个双引号是结束。

C语言的解决方案:反斜杠 \ + 一个字符,两个符号合起来代表一个逻辑字符,占1个字节。

常用的就这几个:

转义字符

干啥的

\n

换行,光标跑到下一行开头

\t

水平制表符,相当于按Tab

\\

输出一个反斜杠本身

\'

在单引号里表示单引号字符

\"

在双引号字符串里输出双引号

三个坑:

反斜杠 \ 和斜杠 / 是两个东西,转义字符只能用反斜杠。写 \n 是换行,写 /n 就是两个普通字符

\n 是一个完整字符,写 '\n' 才对,别拆开

孤零零写一个 \ 后面啥都没有?语法错误,编译器直接报错

对了,\0 也是转义字符,上一节讲过了。

10. 语句

完成一个执行动作的代码就是语句。普通语句以分号 ; 结尾:int a = 10;、printf("hi");。

用大括号 { } 把多条语句包起来,叫复合语句也叫代码块,整体算一条语句。if、for、while后面跟的几乎都是代码块。

记住一件事:大括号后面不要加分号。 加了等于多了一个空语句,虽然不一定报错,但可能带来逻辑问题。

11. 语句分类

① 表达式语句

表达式后面加个分号就是。赋值、计算、函数调用都算:

a = 10;

printf("hi");

② 空语句

就一个分号 ;,啥也不干,语法合法。循环体不需要干活的时候用得上,平时基本见不到。

③ 复合语句

大括号包起来的一坨,整体当一条语句用。if、for、while里天天写。

代码块里定义的变量,出了大括号就没了。这个叫局部变量的作用域,后面学函数的时候会深入讲。

④ 控制语句

改变代码从上到下执行顺序的语句:

分支: if-else

循环: for、while、do-while

跳转: break、continue、return

⑤ 声明语句

定义变量、定义数据类型的语句。int a; 就是最典型的声明语句。

老标准C89要求变量声明必须写在代码块最开头,C99以后随便在哪定义都行。现在的编译器全支持C99,不用管这个老规矩。

两个致命新手坑

坑一:if后面多写分号

if (a > 0); // 这个分号直接把if结束了!

printf("正数"); // 这行不受if控制,永远执行

if条件后面跟了个分号,等于if的体是空语句,后面的printf跟if半毛钱关系没有。这种bug编译不报错,运行结果不对,找起来巨烦。

坑二:不写大括号只管第一行

if (a > 0)

printf("正数"); // 只有这行受if控制

printf("结束"); // 这行永远执行,缩进骗不了编译器

if、while、for 不加大括号,只管辖紧跟的第一条语句。第二行不管你缩进多好看,都不受控制。新手建议永远写大括号,省得后面加代码的时候踩坑。

12. 代码注释

注释是写给人看的,编译器直接忽略,不参与编译,不影响运行。

两种写法:

// 这是单行注释,从//到行尾都是注释

/* 这是多行注释

可以写好几行

直到遇到 */结束

注意:多行注释不能嵌套。你在 /* */ 里面再写一个 /*,编译器会把最近的 */ 当成结束,后面的代码就暴露出来了,直接编译报错。

// 单行注释是C99加的,现在所有编译器都支持。古老的C89不支持,但你基本碰不到C89环境了。

13. 附录

附录A:printf常用格式符速查

printf靠格式符决定数据怎么打印,新手常用的就这几个:

格式符

对应类型

用途

示例

%d

int

打印整数

printf("%d", 10);

%c

char

打印单个字符

printf("%c", 'A');

%s

字符串

打印字符串(遇到\0停)

printf("%s", "hi");

%f

float/double

打印小数

printf("%f", 3.14);

%x

int

十六进制打印

printf("%x", 255);

%%

打印百分号本身

printf("100%%");

用 %s 的时候确保字符串有 \0 结尾,不然printf会一直读内存读到碰巧遇到0,中间全是乱码。

附录B:新手常见编译错误对照表

报错关键词

大概率原因

怎么改

implicit declaration of function 'printf'

没写 #include

加上头文件

'printf' was not declared in this scope

没写头文件(C++环境下)

加上 #include

undefined reference to 'printf'

链接器找不到库(编译参数问题,正常gcc不会出现)

检查编译命令,确保链接了标准库

expected ';' before ...

上一行漏了分号

补分号

expected declaration or statement

大括号不配对

检查 { } 是不是成对

redefinition of 'main'

写了两个main函数

删掉多余的

expected expression

转义字符写错、单独写了 \

检查反斜杠

stray '\xxx' in program

代码里混了中文标点/全角符号

改成英文半角

'xxx' undeclared (first use in this function)

变量名拼错、没定义就用、用了关键字

检查变量名拼写和定义

unterminated comment

多行注释 /* 忘了写 */

补上结束标记

最后说两句

这12个概念看着基础,但后面学指针、学数组、学函数的时候,全是在这些地基上盖楼。\0 搞不清,打印永远有乱码;字符串只读特性不知道,段错误调到怀疑人生;if后面乱加分号,逻辑bug找两小时。

入门阶段那些看起来"莫名其妙"的bug,十有八九根在这。把这篇吃透,少走很多弯路。错误对照表和格式符速查建议收藏,写代码的时候随时翻。

有问题评论区聊,看到会回。