C语言学习笔记

慕课网课程地址:https://www.imooc.com/learn/249

认识C程序

简单来说,一个C程序就是由若干头文件函数组成。

一个简单的 Hello World C 程序

1
2
3
4
5
6
#include<stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}

以上C程序代码中,#include<stdio.h> 为包含头文件,int main(){} 为主函数。

  • #include<stdio.h> 就是一条预处理命令,它的作用是通知C语言编译系统在对C程序进行正式编译之前需要做一些预处理工作

  • 函数就是实现代码逻辑的一个小的单元

    在最新的C标准中,main 函数前的类型为 int 而不是 void

主函数

一个C程序有且只有一个主函数,即 main 函数。C程序就是执行主函数里的代码,也可以说主函数就是C语言中的唯一入口

main 前面的 int 就是主函数的类型

printf() 是格式输出函数,功能就是在屏幕上输出指定的信息。

return 是函数的返回值,根据函数类型的不同,返回的值也是不同的。

\n 是转义字符。

编写规范

  • 一个说明或一个语句占一行,例如:包含头文件、一个可执行语句结束都需要换行
  • 函数体内的语句要有明显缩进
  • 括号要成对写
  • 当一句可执行语句结束的时候末尾需要有分号

注释

多行注释: /* 注释内容 */
单行注释: // 注释一行

基本数据类型

C语言中,数据类型可分为:基本数据类型、构造数据类型、指针类型、空类型四大类。

datatype

标识符

给变量或者函数起的名字就是标识符,标识符可以是字母(A~Z, a~z)、数字(0~9)、下划线_组成的字符串,并且第一个字符必须是字母或者下划线

在使用标识符时还要注意以下几点:

  • 长度最好不要超过8位,因为在某些版本的C中规定标识符前8位有效,当两个标识符前8位相同时,则被认为是同一个标识符
  • 标识符是严格区分大小写
  • 最好选择有意义的英文单词
  • 标识符不能是C语言的关键字

变量及赋值

变量定义的一半形式:数据类型 变量名;

多个类型相同的变量:数据类型 变量名, 变量名, 变量名…;

变量的赋值:

  • 先声明再赋值
  • 声明的同时赋值
1
2
3
4
int num = 10;
int a, b;
a = 1;
b = 2;

基本数据类型

数据类型 说明 字节 应用 示例
char 字符型 1 用于存储单个字符 char sex = ‘m’;
int 整型 2 用于存储整数 int height = 18;
float 单精度浮点型 4 用于存储小数 float price = 11.1;
double 双精度浮点型 8 用于存储位数更多的小数 double pi = 3.1415926;

C语言中不存在字符串变量,字符串只能存在于字符数组中。

格式化输出语句

格式化输出语句,也可以说是占位输出,是将各种类型的数据按照格式化后的类型及指定的位置从计算机上显示。

格式:printf(“输出格式符”, 输出项);

常用格式化符:

格式符 说明
%d 带符号十进制整数
%c 单个字符
%s 字符串
%f 6位小数

输出多个变量,变量之间用逗号隔开

1
2
3
4
5
int a = 10;
float b = 7.56;
char c = 'c';
printf("整数:%d,小数:%f,字符:%c", a, b, c);
// 整数:10,小数:7.560000,字符:c

常量

C语言中常量可以分为直接常量和符号常量

直接常量也成为字面量,可以直接拿来使用,无需定义。

可以使用一个标识符来表示一个常量,称之为符号常量。符号常量在使用之前必须先定义,一般形式为:

#define 标识符 常量值

符号常量的标识符一般习惯使用大写字母,变量的标识符习惯使用小写字母,加以区分。

1
2
3
4
5
6
7
#include <stdio.h>
#define PI 3.14
int main()
{
printf("圆周率:%f\n", PI);
return 0;
}

自动类型转换

自动转换发生在不同数据类型运算时,在编译的时候自动完成。自动转换遵循的规则就好比小盒子可以放进大盒子里,下图表示自动转换规则:

typetransform

char类型数据转换为int类型数据遵循ASCII码中的对应值

字节小的可以向字节大的自动转换,但字节大的不能向字节小的自动转换

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
char c = 'a';
int n = c; //将c赋值给n
float f = c; //将c赋值给f
double d = c; //将c赋值给d
printf("%d\n",n); // 97
printf("%f\n",f); // 97.000000
printf("%lf\n",d); // 97.000000
return 0;
}

强制类型转换

强制类型转换是通过定义类型转换运算来实现的。一般形式为:

(数据类型)(表达式)

1
2
3
4
double a = 6.777;
int b = (int)a;
printf("%f\n", a); // 6.777000
printf("%d\n", b); // 6

使用强制类型转换应注意以下问题:

  • 数据类型和表达式都必须加括号,如 (int)(x/2+y)
  • 转换后不会改变原数据的类型及变量值,只在本次运算中临时性转换
  • 强制转换后的运算结果不遵循四舍五入原则

运算符

算数运算符

名称 运算符号
加法 +
减法 -
乘法 *
除法 /
求余(模运算符) %
自增 ++
自减 --
  • 除法运算中,如果相除的两个数都是整数的话,则结果也为整数,小数部分省略。两数中有一个为小数,结果则为小数

  • 求余运算,只适合用两个整数进行求余运算。运算后的符号取决于被模数的符号,如 (-10)%3 = -1,而 10%(-3) = 1.

赋值运算符

C语言中的赋值运算符分为简单赋值运算符和复合赋值运算符

简单赋值运算符:”=”

复合赋值运算符就是在简单赋值符 “=” 之前加上其他运算符构成,例如:+=、-=、*=、/=、%=

关系运算符

符号 意义
> 大于
>= 大于等于
< 小于
<= 小于等于
== 等于
!= 不等于

关系表达式的值是“真”和“假”,在C程序用整数 1 和 0 表示

逻辑运算符

符号 意义
&& 逻辑与
|| 逻辑或
! 逻辑非

三目运算符

格式:

表达式1 ? 表达式2 : 表达式3;

运算符优先级

youxianji

优先级别为 1 的最高,级别为 10 的最低。

结构语句

if 条件语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(表达式1)
{
// 执行代码块1;
}
...
else if(表达式m)
{
执行代码块m;
}
...
else
{
执行代码块n;
}

while 循环

1
2
3
4
while(表达式)
{
执行代码块
}

do-while 循环

1
2
3
4
do
{
// 执行代码块
} while(表达式);

for 循环

1
2
3
4
for(表达式1; 表达式2; 表达式3)
{
// 执行代码块
}

注意:

  • for 循环中的 表达式1、2、3 均可以省略,但分号不能缺省
  • 表达式1和表达式3可以是多个表达式,以逗号分隔
  • 表达式2一般是关系表达式或逻辑表达式,但也可以是数值表达式或字符表达式,只要其值非零,就执行循环体
  • 表达式中的变量一定要在 for 循环之前定义(与其他语言不同)

三种循环比较

  • 在知道循环次数的情况下,更适合使用 for 循环
  • 不知道循环次数的情况下,使用 while 或 do-while 循环

break 语句

break 语句可以中断循环

  • 在没有循环结构的情况下,break 不能用在单独的 if-else 语句中
  • 在多层循环中,一个 break 语句只跳出当前循环

continue 语句

continue 语句结束本次循环开始执行下一次循环

switch 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
switch(表达式)
{
case 常量表达式1:
执行代码块1
break;
...
case 常量表达式n:
执行代码块n
break;
...
default:
执行代码块n+1;
}

注意:

  • case 子句后如果没有 break,会一直往后执行一直到遇到 break,才跳出 switch 语句
  • switch 后面的表达式语句只能是整型或者字符类型
  • 在 case 后,允许有多个语句,可以不用 {} 括起来

goto 语句

使用格式:

goto 语句标号;

其中语句标号是一个标识符,该标识符一般用英文大写并遵守标识符命名规则,这个标识符加上一个“:”一起出现在函数内某处,执行 goto 语句后,程序将跳转到该标号处并执行其后的语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
int sum = 0;
int i = 1;
// LOOP就是一个有效的标识符
LOOP:if(i<=10)
{
sum += i;
i++;
goto LOOP; // 跳转到LOOP所在位置继续执行
}
printf("sum=%d\n", sum);
return 0;
}

函数

C语言提供了大量的库函数,比如stdio.h提供输出函数。

自定义函数

defineFun

  • [] 包含的内容可以省略,数据类型省略,默认是 int 类型函数;
  • 自定义函数尽量放在 main 函数之前,如果放在main函数后面,需要在main函数之前先声明,声明格式为:[数据类型说明] 函数名称 ([参数])

函数调用

调用形式:

函数名([参数]);

有参函数

[数据类型说明] 函数名称(参数类型 参数名, …)
{
  执行代码块;
  return 表达式;
}

1
2
3
4
5
int learn(int n)
{
printf("小明在慕课网上已经参与学习了%d门课程\n", n);
return 0;
}

形参与实参

形参是定义函数和函数体时使用的参数,实参是在调用时传递给该函数的参数。

  • 形参只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。
  • 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们必须具有明确的值。
  • 在参数传递时,实参和形参在数量上、类型上、顺序上应严格一致,否则会发生类型不匹配的错误。

函数的返回值

return 表达式 或者 return (表达式)

如果函数返回值的类型与函数定义中函数的类型不一致,则以函数返回类型为准,自动进行类型转换

局部变量

函数内部、复合语句内部定义的变量

变量存储类别

C语言根据变量的生存周期来划分,可以分为静态存储方式动态存储方式

  • 静态存储方式:是指在程序运行期间分配固定的存储空间的方式。静态存储区中存放了在整个程序执行过程中都存在的变量,如全局变量

  • 动态存储方式:是指在程序运行期间根据需要进行动态的分配存储空间的方式。动态存储区中存放的变量是根据程序运行的需要而建立和释放的,通常包括:函数形参、自动变量、函数调用时的现场保护和返回地址等。

C语言中存储类别又分为四类:自动(auto)、静态(static)、寄存器的(register)和外部的(extern)

  • 用关键字 auto 定义的变量为自动变量,auto 可以省略,auto不写则隐含定义为“自动存储类别”,属于动态存储方式。

    1
    2
    3
    4
    5
    int fn(int a)
    {
    auto int b, c;
    // ...
    }
  • 用 static 修饰的为静态变量,如果定义在函数内部,称之为静态局部变量;如果定义在函数外部,称之为静态外部变量。

    1
    2
    3
    4
    5
    int fn(int a)
    {
    static int x = 0;
    // ...
    }

静态局部变量属于静态存储类别,在静态存储区内分配存储单元,在整个程序运行期间都不释放;静态局部变量在编译时赋初值,即只赋初值一次;如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。

  • 为了提高效率,C语言允许将局部变量的值放在 CPU 中的寄存器中,这种变量叫“寄存器变量”,用关键字 register 作声明。
    1
    2
    3
    4
    5
    int fn(int a)
    {
    register int i;
    // ...
    }

只有局部自动变量和形参可以作为寄存器变量;一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;局部静态变量不能定义为寄存器变量

  • 用 extern 声明的变量是外部变量,外部变量的意义是某函数可以调用在该函数之后定义的变量。
    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>
    int main()
    {
    extern int x; // 这里声明使用的是外部全局变量
    printf("extern x=%d\n", x);
    return 0;
    }
    int x = 100;

内部函数与外部函数

在C语言中不能被其他源文件调用的函数称为内部函数,由 static 关键字来定义,又被称为静态函数。形式为:

static [数据类型] 函数名()

在C语言中能被其他源文件调用的函数称为外部函数,由 extern 关键字来定义。形式为:

extern [数据类型] 函数名()

在没有指定函数的作用范围时,默认为外部函数,因此 extern 可以省略。

引入源文件#include "test.c"

-------------本文结束感谢您的阅读-------------
Fork me on GitHub