===========================
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) { 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 ? 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);
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); 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); 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);
change(&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); 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; }
|