===========================
2022-7-21
===========================
一.温故知新
指针
malloc
指针的含义 : 指针就是用来存储地址
NULL
指针的定义 : 数据类型 指针名 ;
char * pc ;
char * pi ;
float * pf ;
指针

通过sizeof测试
指针的命名规则和变量的命名规则一致
int i = 0;
int *p;
p = &i;
*p
指针运算符
数据类型 指针名 = 地址 ;
int * p = NULL ;
int *p; -> int
char *p; -> char
指针可以做加减法运算
p+1; p+=1; p++; ++p;
特殊指针
空类型指针(万能指针)
空指针
野指针
容易混淆的声明
const 指针
指针常量
常量指针
数组 函数
指针数组
数组指针
指针函数
函数指针
函数指针数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #include <stdio.h>
#include <stdlib.h>
int add(int a, int b);//函数的声明
int add(int a, int b)//函数的实现
{
return a + b;
}
int main(int argc, char *argv[])
{
int a = 0, b = 0;
int sum = 0;
scanf("%d-%d", &a, &b);
sum = add(a, b);//函数的调用
printf("sum = %d\n", sum);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <stdio.h>
#include <stdlib.h>
int max(int , int );//函数的声明
int max(int x, int y)//函数的实现
{
//x > y ? return x : return y;
return x > y ? x : y;
}
int main(int argc, char *argv[])
{
int a = 0, b = 0;
int sum = 0;
scanf("%d-%d", &a, &b);
sum = max(a, b);//函数的调用
printf("sum = %d\n", sum);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <stdio.h>
#include <stdlib.h>
int isleapyear(int );//函数的声明
int isleapyear(int abc)//函数的实现
{
return (!(abc%4)&&(abc%100)) || (!(abc%400));
}
int main(int argc, char *argv[])
{
int year = 0;
int sum = 0;
scanf("%d", &year);
sum = isleapyear(year);//函数的调用
//如果sum = 1代表是闰年 如果sum = 0代表是平年
sum == 1 ? printf("%d年是闰年!\n", year) : printf("%d年是平年!\n", year);
return 0;
}
|
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
| #include <stdio.h>
#include <stdlib.h>
void func(int ,int);
void func(int a, int b)
{
int min = 0, max = 0;
int i = 0, j = 0;
min = a < b ? a : b;
max = a > b ? a : b;
for(i = min; i <= max; i++)
{
for(j = 2; j < i; j++)
{
if(i % j == 0)
break;
}
if(i == j)
printf("%d\t", i);
}
}
int main(int argc, char *argv[])
{
int a = 0, b = 0;
scanf("%d-%d", &a, &b);
func(a, b);//函数的调用
//func()的功能是寻找最小值 - 最大值之间的素数
return 0;
}
|
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
| #include <stdio.h>
#include <stdlib.h>
void swap(int ,int);
void swap(int a, int b)
{
int tmp = 0;
printf("swap.交换之前a = %d b = %d\n", a, b);
printf("swap.交换之前a = %p b = %p\n", &a, &b);
tmp = a;
a = b;
b = tmp;
printf("swap.交换之后a = %d b = %d\n", a, b);
printf("swap.交换之后a = %p b = %p\n", &a, &b);
}
int main(int argc, char *argv[])
{
int a = 0, b = 0;
scanf("%d-%d", &a, &b);
printf("main.交换之前a = %d b = %d\n", a, b);
printf("main.交换之前a = %p b = %p\n", &a, &b);
swap(a, b);//通过swap()交换变量a b的值
printf("main.交换之后a = %d b = %d\n", a, b);
printf("main.交换之后a = %p b = %p\n", &a, &b);
return 0;
}
|
交换变量值

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
| #include <stdio.h>
#include <stdlib.h>
void swap(int *, int*);
void swap(int *a, int *b)
{
int tmp = 0;
tmp = *a;
*a = *b;
*b = tmp;
}
int main(int argc, char *argv[])
{
int a = 0, b = 0;
scanf("%d-%d", &a, &b);
printf("main.交换之前a = %d b = %d\n", a, b);
swap(&a, &b);//通过swap()交换变量a b的值
printf("main.交换之后a = %d b = %d\n", a, b);
return 0;
}
|
程序员写C语言程序会经历几个阶段
第一阶段 只写一个.c文件,在.c文件中只写一个main函数
把所有的功能都放到main函数中
第二阶段 只写一个.c文件,在.c文件中除了有main函数以外
还会有其他的功能函数的封装
第三阶段 在一个项目工程中存在多个.c或者.h文件
main.c 存放main函数以及功能函数的调用
func.c 存放功能函数的实现
func.h 存放功能函数的声明以及各种定义
makefile 是一个脚本文件(存放的是编译规则)
第四阶段 把func.c制作成库文件
动态库和静态库
函数
当写一个C语言程序时,首先需要写的一个函数就是main函数
1.函数的含义
函数就是一个功能,当调用函数时,会使用这个功能
printf() -> 打印输出
scanf() -> 录入
rand() -> 用来产生随机数
srand() -> 随机种子
time() -> 获取时间的描述
getpid() -> 获取进程ID号
sleep() -> 秒级延时
usleep() -> 微秒级延时
system() -> 调用shell命令
函数的出现是为了减少代码量,减少代码的冗余
例子 : printf函数的代码量有100行左右
如何把一部分的代码封装成一个函数,其实是由程序员决定的
通过是根据每个函数执行一个特定的功能来进行划分的
2.函数组成部分
一般来说函数是由三个部分组成的
1)函数的声明(函数的定义)
其实就是告诉编译器,函数的名称,函数的返回值
以及函数的参数
函数的返回值类型 函数名(参数列表);//该处参数指的是形式参数
函数的返回值类型 函数名 (参数列表);
char * strcpy (char *dest, const char *src);
void * malloc (size_t size);
int rand (void);
void srand (unsigned int seed);
注意 :
1>函数名的命名规则和变量的命名规则一致
2>在写函数的声明时,可以不指定形式参数的名字,
但是必须要有形式参数的数据类型
2)函数的实现
其实就是把函数所代表的功能通过代码进行实现
函数的返回值类型 函数名(参数列表)//该处参数指的是形式参数
{
功能实现的代码
}
注意 :
1>在写函数的实现时,必须要指定形式参数的名字
3)函数的调用
其实就是在代码中使用函数实现的功能
函数名(参数);//该处参数指的是实际参数
形式参数和实际参数是两个不同的内容,可以同名
其实是形式参数来接收实际参数的值的
3.函数的传参
值传递 : 是把实际参数的值传递给形式参数
在这种情况下修改形式参数的值不会影响实际参数
总结: 如果只是想要访问实际参数的值,
不想修改实际参数的值,那么就使用值传递
add(); max(); isleapyear(); printf();
地址传递: 是把实际参数的地址传递给形式参数(指针)
如果通过形式参数修改指向空间的数据
会改变实际参数的值
总结: 如果想要通过形式参数修改实际参数的值
那么就用地址传递
swap(); scanf();
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
| #include <stdio.h>
#include <stdlib.h>
void print(int);
void change(int *);
void print(int a)
{
printf("a = %d\n", a);
}
void change(int *a)
{
scanf("%d", a);
}
int main(int argc, char *argv[])
{
int a = 9527;
print(a);//通过print函数打印变量a的值
change(&a);//通过change函数改变a的值
print(a);//通过print函数打印变量a的值
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 9527;
int *p = &i;
printf("i = %d &i = %p\n", i, &i);
printf("*p = %d p = %p\n", *p, p);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("sizeof(char **) = %ld\n",sizeof(char **));
printf("sizeof(short **) = %ld\n",sizeof(short **));
printf("sizeof(int **) = %ld\n",sizeof(int **));
printf("sizeof(long **) = %ld\n",sizeof(long **));
printf("sizeof(float **) = %ld\n",sizeof(float **));
printf("sizeof(double **) = %ld\n",sizeof(double **));
return 0;
}
|
/*
===========================
作业:
1.把今天讲过的内容完完整整的复习一遍
2.最少把<猜数游戏>和<口算卡>改为多函数的版本
===========================
二级指针
1.二级指针的含义
只要是指针,那就是用来存储地址的
一级指针是用来保存变量的地址的
(可以使用一级指针操控变量)
二级指针是用来保存一级指针的地址的
(可以使用二级指针操控一级指针)
2.二级指针的定义
int i ;
数据类型 指针名 ;
int * p ;
int ** pp ;
3.通过sizeof测试占用存储空间的大小
无论何种类型的二级指针在我当前的机器环境中,
占用空间大小都是8个字节
4.二级指针的命名规则和变量的命名规则一致
5.使用二级指针
1
2
3
4
5
6
7
8
9
10
| 名 i p pp
值 100 0x1000 0x2000
i p pp
*p *pp
**pp
址 0x1000 0x2000 0x3000
&i &p &pp
p pp
*pp
|
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 100;
int *p = &i;
int **pp = &p;
printf("i = %d\n", i);
printf("*p = %d\n", *p);
printf("**pp = %d\n", **pp);
printf("====================\n");
printf("&i = %p\n", &i);
printf("p = %p\n", p);
printf("*pp = %p\n", *pp);
printf("====================\n");
printf("&p = %p\n", &p);
printf("pp = %p\n", pp);
printf("====================\n");
printf("&pp = %p\n", &pp);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 100;
int *p = &i;
int **pp = &p;
printf("&p = %p\n", &p);
printf("pp = %p\n", pp);
pp++;
printf("&p = %p\n", &p);
printf("pp = %p\n", pp);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <stdio.h>
#include <stdlib.h>
void change(int **, int *);
void change(int **p, int *b)
{
*p = b;
}
int main(int argc, char *argv[])
{
int a = 100, b = 200;
int *p = &a;
printf("*p = %d p = %p\n", *p, p);
//change(p, &b);
change(&p, &b);//通过change函数把指针p指向b变量
printf("*p = %d p = %p\n", *p, p);
return 0;
}
|
随机函数
rand(); //功能:就是用来产生随机数的
rand() % 1000; //[0 ~ 999]
rand() % 100 - 50;//[-50 ~ 49]
srand(); //功能:可以保证每一次产生的随机数可变
srand函数在调用时需要有可变的因子
time(NULL); //时间种子
getpid(); //进程种子
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
| #include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
void func(void);
void func(void)
{
int T = 0;//存储随机出的数字
int guess = 0;//存储玩家猜的数字
int num = 1;
srand(getpid());//随机种子
T = rand() % 10;
for(num = 1; ; num++)
{
scanf("%d", &guess);
if(T > guess)
printf("[%d] Small!\n", num);
else if(T < guess)
printf("[%d] Big!\n", num);
else
{
printf("[%d] Bingo!\n", num);
break;
}
}
}
int main(int argc, char *argv[])
{
func();
return 0;
}
|