1.函数调用模型



2.画代码内存四区图
全局区代码测试
char * getstring1()
{
char *p1 = "abcde";
return p1;
}
char * getstring2()
{
char *p2 = "abcde";
return p2;
}
void main()
{
int i= 0;
//指针指向谁就把谁的地址赋给指针变量。
char *p1 = getstring1();
char *p2 = getstring2();
char ******* p3 = NULL; //p3 是个变量
//指针变量和它所执行的内存空间变量是两个不同的概念
strcmp(p1, p2);
system("pause");
}
- 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

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//野指针产生的原因
//指针变量和它所指向的内存空间变量是两个不同的概念
//释放了指针所指的内存空间 但是指针变量本身没有重置成null
//造成释放的时候 通过if (p1 != NULL)
//避免方法: 1)定义指针的时候 初始化成nuLL 2)释放指针所指向的内存空间后,把指针重置成NULL。
void main()
{
char *p1 = NULL;
p1 = (char *)malloc(100);
if (p1 == NULL)
{
return ;
}
strcpy(p1, "11112222");
printf("p1:%s \n", p1);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
if (p1 != NULL)
{
free(p1);
}
printf("hello...\n");
system("pause");
return ;
}
- 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

3.向null地址处copy数据
- 1.strcopy(NULL,”abcdefg”);
- 2.向指定的内存空间copy数据,提示指定的值
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main()
{
char *p1 = NULL;
strcpy(p1, "abcdefg");
printf("hello...\n");
system("pause");
return ;
}
(2)运行结果

4.不断改变指针指向
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main()
{
char buf[128]; //c可以在栈上分配内存
int i;
int j = 0;
char *p2 = NULL;
char *p1 = NULL;
p1 = &buf[0]; //不断的修改p1的值 相当于 不断改变指针的指向
p1 = &buf[1];
p1 = &buf[2];
for (i=0; i<10; i++)
{
p1 = buf[i];
}
p2 = (char *)malloc(100);
strcpy(p2, "abcdefg1212333333333311");
for (i=0; i<10; i++)
{
p1 = p2+i;
printf("%c ", *p1);
}
printf("hello...\n");
system("pause");
return ;
}
- 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
(2)四区图

(3)运行结果

5.直接和间接赋值
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int getFileLen(int *p)
{
*p = 41; // p的值是a的地址 *a的地址间接修改a的值
//在被调用函数里面 通过形参 去 间接的修改 实参的值...
}
//return 只能返回一个结果
int getFileLen2()
{
int a = 100;
return a;
}
//形参的属性
int getFileLen3(int b)
{
b = 100;
}
//1级指针的技术推演
void main()
{
int a = 10; //条件1 定义了两个变量(实参 另外一个变量是形参p)
int *p = NULL;
//修改a的值
a = 20; //直接修改
p = &a; //条件2 建立关联
*p = 30; //p的值是a的地址 *就像一把钥匙 通过地址 找到一块内存空间 求间接的修改了a的值
printf("a: %d \n", a);
{
*p = 40; // p的值是a的地址 *a的地址间接修改a的值 //条件3 *p
printf("a: %d \n", a);
}
getFileLen(&a); //建立关联: 把实参取地址 传递给 形参
printf("getFileLen后 a: %d \n", a);
getFileLen3(a);
printf("getFileLen3后 a: %d \n", a);//发现并没有修改a的值
printf("hello...\n");
system("pause");
return ;
}
- 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
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
(2)四区图

(3)运行结果

6.一级指针到二级指针
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void getMem(char **p2)
{
*p2 = 400; //间接赋值 p2是p1的地址
}
void main()
{
char *p1 = NULL;
char **p2 = NULL;
p1 = 0x11;
p2 = 0x22;
//直接修改p1的值
p1 = 0x111;
//间接修改p1的值
p2 = &p1;
*p2 = 100; //间接赋值 p2是p1的地址
printf("p1:%d \n", p1);
{
*p2 = 200; //间接赋值 p2是p1的地址
printf("p1:%d \n", p1);
}
getMem(&p1);
printf("p1:%d \n", p1);
system("pause");
return ;
}
- 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
(2)运行结果

7.指针做函数参数
- 函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p来改变实参,把运算结果传出来。
- 这便是指针作为函数参数的精髓
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//指针做函数参数
int getMem3(char **myp1, int *mylen1, char **myp2, int *mylen2)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "1132233");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "aaaaavbdddddddd");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
int main()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem3(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem3() err:%d \n", ret);
return ret;
}
printf("p1:%s \n", p1);
printf("p2:%s \n", p2);
if (p1 != NULL)//释放空间
{
free(p1);
p1 = NULL;
}
if (p2 != NULL)//释放空间
{
free(p2);
p2 = NULL;
}
system("pause");
return ret;
}
- 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
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
(2)运行结果

8.间接赋值成立的三个条件
- 条件1:定义1个变量(实参)定义1个变量(形参)
- 条件2:建立关联:把实参取地址传给形参
- 条件3:*形参去间接地的修改了实参的值。
9.字符串的基本操作
-
- C语言的字符串 以零结尾的字符串
-
- 在C语言中没有字符串类型 通过字符数组 来模拟字符串
-
- 字符串的内存分配 堆上 栈上 全局区 (很重要)
(1)字符数组的初始化
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//字符数组 初始化
void main()
{
//1 指定长度
char buf2[100] = {'a', 'b', 'c', 'd'};
//1-1char buf3[2] = {'a', 'b', 'c', 'd'}; //如果初始化的个数大于内存的个数 编译错误
//1-22//后面的buf2[4]-buf2[99] 0
//2 不指定长度 C编译器会自动帮程序员 求元素的个数
char buf1[] = {'a', 'b', 'c', 'd'}; //buf1是一个数组 不是一个以0结尾的字符串
printf("buf2: %s \n", buf2);
printf("buf2[88]:%d \n", buf2[88]);
printf("hello....\n");
system("pause");
return ;
}
- 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

(2)用字符串来初始化字符数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//用字符串来初始化字符数组
//strlen() 长度 不包括0
//sizeof() 内存块的大小
void main()
{
int size = 0;
char buf3[] = "abcd"; // buf3 作为字符数组,应该是5个字节;作为字符串 应该4个字节
int len = strlen(buf3);
printf("buf3字符的长度:%d \n", len); //4
//buf3 作为数组 数组是一种数据类型 本质(固定小大内存块的别名)
size = sizeof(buf3); //
printf("buf3数组所占内存空间大小:%d \n", size); //5
printf("hello....\n");
{
char buf4[128] = "abcd"; // buf
printf("buf4[100]:%d \n", buf4[100]);
}
system("pause");
return ;
}
- 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

(3)通过数组下标和指针操作字符数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//通过数组下标 和 指针
void main()
{
int i = 0;
char *p = NULL;
char buf5[128] = "abcdefg"; // buf5
for (i=0; i<strlen(buf5); i++)
{
printf("%c ", buf5[i]);
}
p = buf5; //buf5 代表数组首元素的地址
for (i=0; i<strlen(buf5); i++)
{
p = p +i;
printf("%c ", *p ) ;
}
printf("hello....\n");
system("pause");
}
- 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
(4)[ ]和*的推导过程
- buf[i] ===> buf[0+i]; ==> *(buf+i);
- []的本质:和*p 是一样 ,只不过是符合程序员的阅读习惯
- buf 是一个指针,只读的常量;
- buf 是一个常量指针,析构内存的时候,保证buf所指向的内存空间安全释放
10.一级指针内存模型建立
(1)代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main61()
{
char buf[20]= "aaaa"; //定义并且初始化
char buf2[] = "bbbb";
char *p1 = "111111";
char *p2 = malloc(100);
strcpy(p2, "3333");
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
(2)内存模型图

10.字符串做函数参数
(1)字符串的复制
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main()
{
char a[] = "i am a student";
char b[64];
int i = 0;
for (i=0; *(a+i) != '\0'; i++)
{
*(b+i) = *(a+i);
}
//0没有copy到b的buf中.
b[i] = '\0'; //重要
printf("a:%s \n", a);
printf("b:%s \n", b);
system("pause");
return ;
}
- 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

(2)字符串copy函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//from形参 形参to 的值 不停的在变化....
//不断的修改了from和to的指向
void copy_str(char *from, char *to)
{
for (; *from!='\0'; from++, to++)
{
*to = *from;
}
*to = '\0';
return ;
}
void main()
{
char *from = "abcdefg";
char buf2[100];
copy_str(from,buf2);
printf("buf2:%s \n",buf2);
system("pause");
return ;
}
- 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


(3)copy_str()演变
//1.
void copy_str(char *from, char *to)
{
for (; *from!='\0';)
{
*to++ = *from++; // 先 *to = *from; 再from++, to++
}
*to = '\0'; //
return ;
}
//2.
void copy_str(char *from, char *to)
{
while( (*to = *from) != '\0' )
{
from ++;
to ++;
}
}
//3.
void copy_str(char *from , char *to)
{
while ( (*to++ = *from++) != '\0')
{
;
}
}
//4.
void copy_str(char *from , char *to)
{
while ( (*to++ = *from++) )
{
;
}
}
//5.重点***
//不要轻易改变形参的值, 要引入一个辅助的指针变量. 把形参给接过来.....
int copy_str26_good(char *from , char *to)
{
char *tmpfrom = from;
char *tmpto = to;
if ( from == NULL || to == NULL)
{
return -1;
}
while ( *tmpto++ = *tmpfrom++ ) ; //空语句
printf("from:%s \n", from);
}
- 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
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
11.项目开发字符串模型
- 要求:
- char *p = “abcd111122abcd3333322abcd3333322qqq”;
- 求字符串p中 abcd出现的次数
(1)使用strstr(str, str2)函数配合do_while()
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main()
{
int ncount = 0;
//初始化 让p指针达到查找的条件
char *p = "11abcd111122abcd3333322abcd3333322qqq";
do
{
p = strstr(p, "abcd");
if (p != NULL)
{
ncount++; //
p = p + strlen("abcd"); //指针达到下次查找的条件
}
else
{
break;
}
} while (*p != '\0');
printf("ncount:%d \n", ncount);
system("pause");
return;
}
- 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

(2)使用strstr(str, str2)函数配合while()
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main()
{
int ncount = 0;
//初始化 让p指针达到查找的条件
char *p = "2abcd3333322qqqabcd";
while (p = strstr(p, "abcd"))
{
ncount++;
p = p + strlen("abcd"); //让p指针达到查找的条件
if (*p == '\0')
{
break;
}
}
printf("ncount:%d \n", ncount);
system("pause");
}
- 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

(3)自定义函数完成
- 请自定义函数接口,完成上述需求
- 自定义的业务函数 和 main函数必须分开
代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int getCount(char *mystr /*in*/, char *sub /*in*/, int *ncount)
{
int ret = 0;
int tmpCount = 0;
//初始化 让p指针达到查找的条件
char *p = mystr; //不要轻易改变形参的值
if (mystr == NULL || sub == NULL || ncount == NULL)
{
ret = -1;
printf("func getCount() err:%d (mystr==NULL || sub==NULL ||ncount==NULL) \n", ret);
return ret;
}
do
{
p = strstr(p, sub);
if (p != NULL)
{
tmpCount++;
p = p + strlen(sub); //指针达到下次查找的条件
}
else
{
break;
}
} while (*p != '\0');
*ncount = tmpCount; //间接赋值是指针存在的最大意义
return ret;
}
int main()
{
int ret = 0;
char *p = "abcd111122abcd3333322abcd3333322qqq";
int count = 0;
char sub[] = "abcd";
ret = getCount(p, sub, &count);
if (ret != 0)
{
printf("func getCount() err:%d \n", ret);
return ret;
}
printf("count:%d \n", count);
system("pause");
}
- 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
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
运行结果
