序言
本章我们将要学习的是一下几个内容
指针与函数 结构体 动态内存分配 算法时间复杂度
指针与函数
我们依旧是拿题来学习这个知识:
设计一个函数,传入两个 int 参数,并交换着两个参数的值
这个程序听起来很简单吧,我们可以直接用一个中间变量来进行传递他们的变量值
1 2 3 4
| int temp; temp = a; a = b; b = temp;
|
正常我们这样写就可以了。
但是如果我们学了指针之后,我们就可以更加方便了
现在我们先把上面的那个代码完整补充一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <stdio.h>
void swap(int x,int y) { int temp; temp = x; x = y; y = temp; printf("交换后x=%d,y=%d\n",x,y); }
int main() { int a = 10; int b = 20; swap(a,b); printf("a=%d,b=%d\n",a,b); return 0; }
|
运行结果:
交换后x=20,y=10
a=10,b=20
我们可以看到一个很奇怪的事情,我们在 main 函数中的第二个 printf 中输出出来的值是没有交换的。
为什么呢?
因为我们传入 swap()中的不是 m 与 n 这两个变量,而是 m 与 n 的变量的值 。所以我们在后面在运行 printf 的时候,m 与 n 的值才会没有变化
现在我们来通过指针来让他的值彻底改变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <stdio.h>
void swap(int *x,int *y) { int temp; temp = *x; *x = *y; *y = temp; printf("交换后x=%d,y=%d\n",*x,*y); }
int main() { int a = 10; int b = 20; swap(&a,&b); printf("a=%d,b=%d\n",a,b); return 0; }
|
我们知道指针变量是用来保存某个数据在内存中的地址,那我们用取地址符去传入一个 a 和 b 的地址,那么我们的指针变量就可以直接根据地址去更改 a 和 b 的值了。
我们在大脑中要有一个快速的转换,在函数里面看到了指针就得想到地址,想到地址就不得不想到取地址符。
我们可以看看用了指针之后,我们的 swap 函数接收的参数有什么变化。

从接收 m 与 n 的值转换成了接收 m 与 n 的地址。
指针与数组
在 C 语言中,指针与数组的关系十分密切。通过数组下标能完成的操作都可以通过指针完成。
一般来说,用指针编写的程序比用数组下标编写的程序执行速度快。
我们通过一个小程序来学习一个小玩意:
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h> int main() { int a[] = {1,2,3,4,5}; int *p; p = a;
printf("%p\n",a); printf("%p\n",p); printf("%d\n",*p); return 0; }
|
输出结果:
00000017db5ff730
00000017db5ff730
1
我们可以看到我们的指针 p 获取的数数组的首地址。我们获取了首地址,那我们也可以获取到数组中的首个元素。
那如果我想要获取 2,3,4,5 该怎么办呢?
一个数组,他们地址肯定是连续的,假设 1 的地址是 101,那么 2 的地址就是 105 然后 109,114.以此类推,我们可以写一个循环,可以使用 sizeof 来算出我们数组中一个数的字节,然后让我们的 p 每次都加这个字节。以此类推就可以了。
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h> int main() { int a[] = {1,2,3,4,5}; int *p; p = a;
for (int i = 0; i < sizeof(a)/sizeof(a[0]);i++) { printf("%d ",*(p+i)); } return 0; }
|
但是有一个很奇怪的一个点啊,这里的 i 是从 0-4 的,然后我们是(p+i),那从感官上来看就像是 101,102,103,104 这样的,但是为什么我们运行出来没有问题?
因为在对指针做算数运算的时候,我们的的程序其实是这样玩的
p = p+1; -> p = p + 1 * 4;
给指针加上一个整数,实际上加的是这个整数和指针数据类型对应字节的乘积。
结构体
结构体本身也是一种数据类型,不过是自己自定义的数据类型。
比如说我想用一种数据类型,来表示一个坐标上的一个点,能表示出来吗?
有人可能会想到我直接设两个变量一个 x 一个 y。这样不行,因为这是两个变量。
我们想要的是一个数据类型,就一个变量就可以完成这件事。这个时候我们就可以使用结构体了
本质上结构体就是一个多个变量的集合。
结构上怎么写:
1 2 3 4 5 6 7 8 9 10 11 12
| struct point { int x; int y; };
struct 结构体名 { 数据类型 变量名; 数据类型 变量名; };
|
结构体的初始化与调用
初始化:
1 2
| struct 结构体名 结构体名; struct point p;
|
调用:
1 2 3
| 变量名.结构体内部变量名 = 值. p.x = 10; p.y = 15;
|
我们这里把代码完善一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <stdio.h>
struct point { int x; int y; };
int main() { struct point p; p.x = 5; p.y = 6; printf("p.x=%d,p.y=%d\n",p.x,p.y); return 0; }
|
那现在假设我要创建一个数据类型是 student。
那我们在数据类型里面应该包含
- stuId
- stuName
- sex
- homeTown
- major
ok,那我们现在来完善一下我们这个代码
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
| #include <stdio.h> #include <string.h>
struct student { char stuid[20]; char stuName[20]; char sex[5]; char homeTown[50]; char major[20]; } stu;
int main() { strcpy(stu.stuid,"20230101"); strcpy(stu.stuName,"张三"); strcpy(stu.sex,"男"); strcpy(stu.homeTown,"北京"); strcpy(stu.major,"计算机"); printf("------------------------------\n"); printf("student id=%s\n",stu.stuid); printf("student name=%s\n",stu.stuName); printf("student sex=%s\n",stu.sex); printf("student home=%s\n",stu.homeTown); printf("student major=%s\n",stu.major); printf("------------------------------\n"); return 0; }
|
我们这里需要注意一下,在传入字符类型的时候,我们需要使用的 strcpy。
typedef
给一个数据类型起一个别名。
typedef 数据类型 别名
typedef int zx
那么后续我就可以直接使用 zx 来充当我们这个 zx 了。
但是我觉得很奇怪?我有 int 了我为什么不直接使用 int?而是在去命名为一个 zx,然后再去使用这个 zx 去替代我们的 int 呢?这不是脱裤子放屁吗?
原因是这样的:
每次声明结构体变量的时候,都要写 struct 关键字,这很麻烦,而且逻辑上也很难受,但是我们的 typedef 就可以完美的解决这个问题。
比如说我们看这个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include<stdio.h> #include<string.h>
struct point { int x; int y; };
int main() { struct point stu; stu.x = 5; stu.y = 6; printf("stu.x=%d,stu.y=%d\n",stu.x,stu.y); return 0; }
|
现在我们来看看这个 typedef 的类型定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| typedef struct 结构体名 { 数据类型 变量名; 数据类型 变量名; ...... }别名;
------------------------------------------------------ typedef struct { 数据类型 变量名; 数据类型 变量名; ...... }别名;
|
一旦我们这个 typedef 给这个结构体起了别名的之后,我们写代码就可以直接用这个别名来声明一个变量了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include<stdio.h> #include<string.h>
typedef struct { int x; int y; }point;
int main() { point p; p.x = 5; p.y = 6; printf("stu.x=%d,stu.y=%d\n",p.x,p.y); return 0; }
|