初识C语言

什么是C语言?

C语言 是一门 通用计算机编程语言,广泛应用于底层开发。C语言是一门 面向过程 的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。

数据类型

  • 注意:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
*/

#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char)); // 1
printf("%d\n", sizeof(short)); // 2
printf("%d\n", sizeof(int)); // 4
printf("%d\n", sizeof(long)); // 4
printf("%d\n", sizeof(long long)); // 8 >=int
printf("%d\n", sizeof(float)); // 4
printf("%d\n", sizeof(double)); // 8
printf("%d\n", sizeof(long double));// 8
return 0;
}

变量、常量

变量:生活中有些值是可变的,如 年龄,体重…,因此需要变量来表示

常量:有可变的,就有不可变的,如 身份证号码,性别…

定义变量的方法

1
2
3
int age = 150;
float weight = 45.5f;
char ch = 'w';

变量的分类

  • 局部变量:是指 在一个函数内部的变量,它的 作用域 仅限于函数内部, 离开该函数后就是无效的。
  • 全局变量:是指 在所有函数外部定义的变量,它的 作用域 默认是整个工程。

实例

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}

输出

1
2
global = 2020
//当局部变量和全局变量同名的时候,局部变量优先使用。

字符串

字符串:由 双引号 引起来的 一串字符 称为字符串字面值,或者简称字符串

注:字符串的 结束标志 是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串 内容

实例

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
char arr1[] = "bit";
char arr2[] = {'b', 'i', 't'};
char arr3[] = {'b', 'i', 't', '\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}

输出

1
2
3
bit
bit烫烫烫
bit

解析:arr1中存储的是'b' 'i' 't' '\0'arr2中存储的是'b' 'i' 't'arr3中存储的是'b' 'i' 't' '\0';输出字符串时,遇到'\0'才会停止,arr1和arr3都有'\0',输出到'\0'就停止,arr2中没有'\0',因此会一直输出直至遇到'\0'字符串会自动补上 '\0'

转义字符

我们要在屏幕上打印一个目录: c:\code\test.c,我们该如何写代码

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

输出

1
c:\code    est.c

其中\t \n就是为转义字符,改变了字符原本的含义。

转义字符
转义字符释义
\?在书写连续多个问号时使用,防止他们被解析成三字母词
\‘用于表示字符常量
\“用于表示一个字符串内部的双引号
\\用于表示一个反斜杠,防止它被解释为一个转义序列符
\a警告字符,蜂鸣
\b退格符
\f进纸符
\n换行
\r回车
\t水平制表符
\v垂直制表符
\dddddd表示1~3个八进制的数字。 如: \130 X
\xdddd表示2个十六进制数字。 如: \x30 0

实例

1
2
3
4
5
6
7
8
9
//程序输出什么?
#include <stdio.h>
int main()
{
printf("%d\n", strlen("abcdef"));
// \62被解析成一个转义字符
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}

输出

1
2
6
14

解析:strlen输出字符串时,不算 \0,第一个printf输出6;第二个printf,\t算一个字符,\62算一个字符,为什么不是\628为一个字符?因为八进制不能有8,因此一定为16进制,转义字符的16进制后跟两位数字。因此这么一长串14个字符长度。

注释

注释的作用:

  • 代码中有不需要的代码可以直接删除,也可以注释掉
  • 代码中有些代码比较难懂,可以加一下注释文字

C语言两种注释:

  • / 不可嵌套注释 /
  • // 可以注释一行也可以注释多行(多行需要多个 //)

选择语句

生活中会遇到选择,例如,你选择是去工地还是去腾讯还是去阿里巴巴。C语言程序中也会有选择。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int coding = 0;
printf("你会去敲代码吗?(选择1 or 0):>");
scanf("%d", &coding);
if(coding == 1)
{
prinf("坚持,你会有好offer\n");
}
else
{
printf("放弃,回家卖红薯\n");
}
return 0;
}

循环语句

生活中与许多循环的事情,例如我们走路,就是不停的循环,左脚 右脚 左脚 右脚 …,然而C语言也是有循环的。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//while循环的实例
#include <stdio.h>
int main()
{
printf("加入比特\n");
int line = 0;
while(line<=20000)
{
line++;
printf("我要继续努力敲代码\n");
}
if(line>20000)
printf("好offer\n");
return 0;
}

函数

函数:是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

函数的特点:就是简化代码,代码复用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
int z = x+y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = Add(num1, num2);
printf("sum = %d\n", sum);
return 0;
}

数组

数组:用来 存储一组相同类型元素的集合

数组的定义

1
2
// 元素类型 数组名[元素个数];  // 元素个数为大于零的整数常量
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素

数组的下标

C语言规定:数组的 每个元素都有一个下标下标是从0开始 的,最大下标数组长度-1

1
2
int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9

image-20230104213543970

操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1)算术操作符
+ - * / %

2)移位操作符
>> <<

3)位操作符
& ^ |

4)赋值操作符
= += -= *= /= &= ^= |= >>= <<=

5)单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换

6)关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”

7)逻辑操作符
&& 逻辑与
|| 逻辑或

8)条件操作符
exp1 ? exp2 : exp3

9)逗号表达式
exp1, exp2, exp3, …expN

10)下标引用、函数调用和结构成员
[] () . ->

常见关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
共32个
1)基本数据类型(5个):
void:声明函数无返个回值或无参数,声明无类型指针,显式丢弃运算结果
char:字符型类型数据,属于整型数据的一种
int:整型数据,通常为编译器指定的机器字长
float:单精度浮点型数据,属于浮点数据的一种
double:双精度浮点型数据,属于浮点数据的一种

2)类型修饰关键字(4个):
short:修饰int,短整型数据,可省略被修饰的int。
long:修饰int,长整形数据,可省略被修饰的int。
signed:修饰整型数据,有符号数据类型
unsigned:修饰整型数据,无符号数据类型

3)复杂类型关键字(5个)
struct:结构体声明
union:共用体声明
enum:枚举声明
typedef:声明类型别名
sizeof:得到特定类型或特定类型变量的大小

4)存储级别关键字(6个):
auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配
static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部
register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数
extern:指定对应变量为外部变量,即在另外的目标文件中定义,可以认为是约定由另外文件声明的对象的一个“引用“
const:与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)
volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值

5)跳转结构(4个):
return:用在函数体中,返回特定值(或者是void值,即不返回值)
continue:结束当前循环,开始下一轮循环
break:跳出当前循环或switch结构
goto:无条件跳转语句

6)分支结构(5个)
if:条件语句
else:条件语句否定分支(与if连用)
switch:开关语句(多重分支语句)
case:开关语句中的分支标记
default:开关语句中的“其他”分治,可选

7)循环结构(3个)
for:for循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2...循环,其中2为循环条件
do:do循环结构,do 1 while(2);的执行顺序是1->2->1...循环,2为循环条件
while:while循环结构,while(1) 2;的执行顺序是1->2->1...循环,1为循环条件、

#define 定义常量和宏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include <stdio.h>
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);

sum = 10*ADD(2, 3);
printf("sum = %d\n", sum);

return 0;
}

指针

指针:也就是内存地址,指针变量是用来存放内存地址的变量

内存地址:为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。

如何取出变量地址?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
int num = 10;
&num;//取出num的地址
//注:这里num的4个字节,每个字节都有地址,取出的是 第一个字节的地址(较小的地址)
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0;
}

如何存储地址

1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
int num = 10;
int *p = &num;
*p = 20;
return 0;
}

指针变量的大小

指针的大小不是由指针类型决定,而是由操作系统的位数决定

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%d\n", sizeof(char *));
printf("%d\n", sizeof(short *));
printf("%d\n", sizeof(int *));
printf("%d\n", sizeof(double *));
return 0;
}

结论:指针大小在32位平台是4个字节,64位平台是8个字节。