温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C 提高2 间接赋值(*p) 是指针存在的最大意义

发布时间:2020-06-12 09:34:53 来源:网络 阅读:816 作者:990487026 栏目:开发技术


1野指针强化:

#include <stdio.h> #include <stdlib.h> #include <string.h> // 野指针产生的原因 //指针变量和它指向的内存空间变量是两个不同的概念 //释放了指针所指向的内存空间,但是指针变量本省没有重置为NULL //造成释放的时候,通过if(p1 != NUll) //避免方法: // 1)定义指针的时候,初始化成NULL // 2)释放指针所指向的内存空间,把指针重置成NULL int main() {	char *p1 = NULL;	p1 = (char *)malloc(100);	if (p1 == NULL)	{	printf("没有分配到堆空间 \n");	return 0;	}	strcpy(p1, "1234567890");	printf("%s \n", p1);	if (p1 != NULL)	{	free(p1);	//p1 = NULL;//如果没有这个步骤,下面的再次释放就导致程序出错(VS2013)	}	if (p1 != NULL)	{	free(p1);	} }

C 提高2 间接赋值(*p) 是指针存在的最大意义





NULL 地址写入数据

不可预料的地址写入数据

不断改变指针的指向:

C 提高2 间接赋值(*p) 是指针存在的最大意义

C 提高2 间接赋值(*p) 是指针存在的最大意义


C 提高2 间接赋值(*p) 是指针存在的最大意义


#include <stdio.h> #include <stdlib.h> #include <string.h> int main() {	char  buf[20] = { 'a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5' };	char *p1 = NULL;	char *p2 = NULL;	p1 = &buf[0];	p1 = &buf[1];	p1 = &buf[2];	int i = 0;	for (i = 0; i < 10; i++)	{	p1 = &buf[i];	printf("%c ", *p1);	}	p2 = (char *)malloc(20);	strcpy(p2,"1234567890");	for (i = 0; i < 10; i++)//不断的修改指针的值,相当于不断改变指针的指向	{	p1 = p2+i;//注意p2的步长是char	printf("%c ",*p1);	}	free(p2);	system("pause"); } 编译运行: C:\Users\chunli>gcc main.c & a a 1 b 2 c 3 d 4 e 5 1 2 3 4 5 6 7 8 9 0 请按任意键继续. . .



字面量:

#include <stdio.h> #include <stdlib.h> #include <string.h> int main() {	//结论:字面量不能取地址,没有放在栈区,也没有放在堆区,因为没法取其地址	//我觉得放在代码区	int i = 0;	 //字面量 0   0不能取地址	for (i = 0; i < 10; i++) //字面量 10  10不能取地址	{	printf("Hello World! \n");	} } 便于运行: C:\Users\chunli>gcc main.c & a Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!


从0级指针到1级指针:

#include <stdio.h> #include <stdlib.h> #include <string.h> int fun1() {	int a = 20;	return a; } int fun2(int a) {	a = 30; } int fun3(int *a) {	*a = 40; } int main() {	int a = 10;	int *p = NULL;	p = &a;	printf("%d \n",*p);	fun1();	printf("%d \n", *p);	fun2(a);	//只是把a的数值传过来,用来初始化函数的值,除此之外,函数内与a没有任何关系了	printf("%d \n", *p);	fun3(&a);	//只有把a的地址传过来,才能对a进行修改	printf("%d \n", *p);	system("pause"); }  /* 编译运行: 10 10 10 40 请按任意键继续. . .  */


 从1级指针到2级指针:

 #include <stdio.h> #include <stdlib.h> #include <string.h> void fun1(char **p2)	//只有这种方法才能修改一级指针的数值 {	*p2 = 0xff;	//间接修改一级指针的值,而不是修改一级指针指向的内存块 } void fun2(char *p2)	//这种方法永远也不可能修改传过来的一级指针的数值 {	//char *p2	就相当于是在这里定义了一个p2指针变量,和外界的一级指针没有任何关系	p2 = 0xf; } int main() {	char *p1 = NULL;	char *p2 = NULL;	//直接修改p1的值	p1 = 0x22;	p2 = 0x55;	//间接是修改p1的值	p2 = &p1;	 //把p1的地址装入p2	*p2 = 100;	 //把变量p1的值修改为100	printf("%d \n",p1);	//把p1的数值打印出来	fun1(&p1);	//间接修改一级指针的值,而不是修改一级指针指向的内存块	printf("%d \n", p1);	//把p1的数值打印出来	fun2(p1);	printf("%d \n", p1);	//把p1的数值打印出来	system("pause"); }  /*  编译运行:  100  255  255  请按任意键继续. . .  */




【重要概念】


间接赋值(*p) 是指针存在的最大意义

#include <stdio.h> #include <stdlib.h> #include <string.h> void fun1(char **myp1, int *mylen1, char **myp2, int *mylen2) { 	int ret = 0;	char *tmp1 = NULL;	char *tmp2 = NULL;	//间接赋值	tmp1 = (char *)malloc(100);	strcpy(tmp1, "1234567890");	*mylen1 = strlen(tmp1);// 1级指针	*myp1 = tmp1;	   //2级指针	tmp2 = (char *)malloc(200);	strcpy(tmp2, "abcdefg");	*mylen2 = strlen(tmp2);// 1级指针	*myp2 = tmp2;	   //2级指针 } int main() {	/*	原来p1的值是NULL,通过函数调用,p1指向了一块内存区域	*/	char	*p1 = NULL;	char	*p2 = NULL;	int	len1 = 0;	int	len2 = 0l;	int	ret = 0;	fun1(&p1, &len1, &p2, &len2);	if (ret != 0)	{	printf("error :%d \n", ret);	}	printf("%s \n", p1);	printf("%s \n", p2);	if (p1 != NULL)	{	free(p1);	p1 = NULL;	}	if (p2 != NULL)	{	free(p2);	p2 = NULL;	}	system("pause");	return ret; }  /*  编译运行:  1234567890  abcdefg  请按任意键继续. . .  */




间接赋值的成立条件:

#include <stdio.h> #include <stdlib.h> #include <string.h> void fun1(int *p) {	*p = 50; } int main() {	//条件1,定义了2个变量	int a = 0;	int *p = NULL;	//条件2,建立关联	p = &a;	//条件3,*p间接修改	*p = 10;	printf("%d \n",a);	//一级指针与函数	fun1(&a); //把实参的地址传给形参,建立关联	printf("%d \n", a);	system("pause");	return 0; }  /*  编译运行:  10  请按任意键继续. . .  */


//间接赋值的应用场景

 #include <stdio.h> #include <stdlib.h> #include <string.h> /* 间接赋值成立的三个条件: 条件1:定义变量(实参),定义变量(形参) 条件2:建立关联 条件3:形参去间接的修改了实参的值 */ //间接赋值的应用场景 // 条件1 2 3 写在一个函数中 int main() {	char from[100] = { 0 };	char   to[100] = { 0 };	char *p1 = from;	char *p2 = to;	strcpy(from,"112233445566");	while (*p1 != '\0')	{	*p2++ = *p1++;	}	printf("%s \n",to);	system("pause");	return 0; }  /*  编译运行:  112233445566  请按任意键继续. . .  */


字符串与一级指针  专题 ---  //字符数组的初始化

#include <stdio.h> #include <stdlib.h> #include <string.h> //字符串与一级指针  专题 ---  //字符数组的初始化 // 1 C语言中的字符串是以数字0结尾的 // 2 在C语言中没有字符串类型,通过字符数组来模拟字符串 // 3 字符串的内存分配可以在堆上 栈上 常量区  int main() {	char buf1[100] = { 'a', 'b', 'c', 'd' };//除前面4个外,其他全是0	printf("%d \n",buf1[99]);	//char buf2[2] =   { 'a', 'b', 'c', 'd' };//大于初始化的内存个数,编译器报错	char buf3[] =    { 'a', 'b', 'c', 'd' };//这不是以0结尾的字符串	char buf4[] = "abcd";	//数组的大小是5,字符长度是4	int size = sizeof(buf4);	int len = strlen(buf4);	printf("size=%d,  len=%d \n",size,len);	system("pause");	return 0; }  /*  编译运行:  0  size=5,  len=4  请按任意键继续. . .  */




字符串与一级指针  专题 -- 用数组和指针操作字符串

 #include <stdio.h> #include <stdlib.h> #include <string.h> //字符串与一级指针  专题 -- 用数组和指针操作字符串 //普通指针与数组变量名字的区别 int main() {	int i = 0;	char *p1 = NULL;	char buf1[128] = "abcdefg";	for (i = 0; i < strlen(buf1);i++)	{	printf("%c ",buf1[i]);	}	//用指针操作字符串	p1 = buf1;//buf代表数组元素的地址,这句话是错误的。应该说,buf代表数组首元素的地址	for (i = 0; i < strlen(buf1); i++)	{	printf("%c  ", *(p1 + i)); //效果一样	printf("%c  ", *(buf1 + i)); //效果一样 相当于buf1[i]	//[] 到* 的推导过程	//buf1[i] => buf1[0+i] => *(buf+i)  ,buf代表数组首元素的地址	//其实[] 与 * 操作数组,没有多大的区别,只是中括号便于人们的阅读	}	//不允许的操作     //buf1 = buf1 + 1;     左操作数必须为左值	  	system("pause");	return 0; } // 中括号[]的本质:和*是一样,只不过是符合程序员的阅读习惯 // buf是一个指针,只读的常量,buf是一个常量指针。 //为什么这么做? //buf是一个常量指针,析构内存的时候,保证buf空间完整释放  /*  编译运行: a b c d e f g a  a  b  b  c  c  d  d  e  e  f  f  g  g  请按任意键继续. . .  */



一级指针 内存模型的建立

C 提高2 间接赋值(*p) 是指针存在的最大意义

 #include <stdio.h> #include <stdlib.h> #include <string.h> //一级指针 内存模型的建立 int main() {	char buf1[20] = "aaa";	char buf2[]   = "bbbb";	char *p1 = "11111111111111";	char *p2 = malloc(100);	strcpy(p2,"333333");	system("pause");	return 0;	//见图 } /*  编译运行:  */

C 提高2 间接赋值(*p) 是指针存在的最大意义



字符串做函数参数

#include <stdio.h> #include <stdlib.h> #include <string.h> //字符串做函数参数 int 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' 并不会存入	}	b[i] = '\0'; //'\0' 并不会存入	printf("%s \n",b);	system("pause");	return 0; } /*  编译运行:  i am a student  请按任意键继续. . .  */



字符串拷贝,3种方法

C 提高2 间接赋值(*p) 是指针存在的最大意义

#include <stdio.h> #include <stdlib.h> #include <string.h> //字符串拷贝,3种方法 void copy_str1(char *from, char *to) {	while (*from != '\0')	//当遇到0就跳出来了	{	//指针的指向不断变化,小心啊	// ++ 优先级高	*to++ = *from++; //'\0' 并不会存入	//相当于先 *to = *from, 在to++  from++	}	*to = '\0';	return; } void copy_str2(char *from, char *to) //优化一下 {	while ((*to = *from) != '\0')	//先把值赋过去,再判断	{	*to++;	*from++; 	} } //经典程序之一  字符串拷贝 void copy_str(char *from, char *to) //再优化一下 {	while (*to++ = *from++);	//先把值赋过去,再判断 } int main() {	char *from = "Hello";	char buf[100] = {0};	copy_str(from,buf);	printf("%s \n",buf);	system("pause");	return 0; } /*  编译运行:  i am a student  请按任意键继续. . .  */



经典程序之一  字符串拷贝

#include <stdio.h> #include <stdlib.h> #include <string.h> //字符串拷贝,3种方法 //经典程序之一  字符串拷贝 //不要轻易改变形参的值 int copy_str(char *from, char *to) //再优化一下 {	char * tmp_to = to; //引进一个辅助	if (from == NULL  || to == NULL) return -1;	while (*to++ = *from++);	//先把值赋过去,再判断	//不能出现 printf("%s \n",to)这样的语句,因为to已经改变了	printf("%s \n",tmp_to);	return 0; } int main() {	int ret = 0;	char *from = "Hello";	//char *buf = NULL;	char buf[20] ;	ret = copy_str(from,buf);	if (ret != 0)	{	printf("fun copy_str error %d  \n", ret);	}	printf("%s \n",buf);	system("pause");	return ret; } /*  编译运行:  i am a student  请按任意键继续. . .  */


项目开发字符串模型  do while 模型

#include <stdio.h> #include <stdlib.h> #include <string.h> //项目开发字符串模型  do while 模型 int main() {	int count = 0;	char *p = "11abcd123abcd234abcd23abcd2345abcd";	do	{	p = strstr(p, "abcd");	if (p != NULL)	{	count++;	p = p + strlen("abcd");	}	else	{	break;	}	} while (*p != '\0');	printf("%d \n" ,count);	system("pause");	return 0; } /*  编译运行:  */




项目开发字符串模型  while 模型

 #include <stdio.h> #include <stdlib.h> #include <string.h> //项目开发字符串模型  while 模型 int main() {	int count = 0;	char *p = "11abcd123abcd234abcd23abcd2345abcd";	while (p=strstr(p,"abcd"))	{	count++;	p = p + strlen("abcd");	if (*p == '\0')	{	break;	}	} 	printf("%d \n" ,count);	system("pause");	return 0; } /*  编译运行:  */



项目开发字符串模型  while 模型  --  API封装

 #include <stdio.h> #include <stdlib.h> #include <string.h> //项目开发字符串模型  while 模型  --  API封装 int getCount(char *String/*in*/, char *sub/*i*/, int *count/* out*/) {	int tmp_count = 0;	int ret = 0;	char *p = String;	if (String == NULL || sub == NULL)	{	ret = -1;	printf("fun getCount  error String == NULL || sub == NULL %d \n ",ret);	return ret;	}	while (p = strstr(p, sub))	{	tmp_count++;	p = p + strlen(sub);	if (*p == '\0')	{	break;	}	}	*count = tmp_count;	return 0; } int main() {	int ret = 0;	int count = 0;	char *p1 = "11abcd123abcd234abcd23abcd2345abcd";	char *p2 = "abcd";	ret = getCount(p1,p2,&count);	if (ret != 0)	{	printf("fun fetCount error %d \n",ret);	}	printf("%d \n" ,count);	system("pause");	return ret; } /*  编译运行:  */


练习题:

C 提高2 间接赋值(*p) 是指针存在的最大意义

C 提高2 间接赋值(*p) 是指针存在的最大意义


第一题,我的答案:

#include <stdio.h> #include <stdlib.h> #include <string.h> int str_del(const char *str1/*in*/, char * str2/*out*/) {	int ret = 0;	if (str1 == NULL || str2 == NULL)	{	ret = -1;	printf("fun str_del  str1 == NULL || str2 == NULL  error: %d \n",ret);	return ret;	}	char *p = str1;	while (*p == ' ')	{	p++;//跳出空格	}	strcpy(str2, p);//从第一个非空格开始,写入原字符串	int len = strlen(str2);	if (str2[len-1] == ' ')//如果最后一位有空格	{	p = str2+len-1;//找到最后一个空格的位置	while (*p == ' ')	{	*p = 0;	p--;	}	}	return ret; } int main() {	int ret = 0;	char *str1 ="     abc 123   ";	char str2[128];	ret = str_del(str1,str2);	if (ret != 0)	{	printf("error in fun str_del code:%d\n",ret);	return ret;	}	printf("%s", str2);	system("pause");	return ret; } /*  编译运行:  abc 123请按任意键继续. . .  */



第二题,我的答案:

#include <stdio.h> #include <stdlib.h> #include <string.h> int getstr(const char *str1/*in*/, char * str2/*out*/, char * str3/*out*/) {	int ret = 0;	if (str1 == NULL || str2 == NULL || str3 == NULL)	{	ret = -1;	printf("fun str_del  str1 == NULL || str2 == NULL || str3 == NULL  error: %d \n",ret);	return ret;	}	char *p1 = str1;	char *p2 = str2;	char *p3 = str3;	int i = 0;	while (*p1 != '\0')	{	if (i % 2)	*p2++ = *p1;	else	*p3++ = *p1;	i++;	p1++;	}	return ret; } int main() {	int ret = 0;	char *string ="1a2b3c4da1b2c3d4";	char str1[128] = { 0 };	char str2[128] = { 0 };	ret = getstr(string,str1,str2);	if (ret != 0)	{	printf("error in fun str_del code:%d\n",ret);	return ret;	}	printf("str1=%s\n", str1);	printf("str2=%s\n", str2);	system("pause");	return ret; } /*  编译运行:  str1=abcd1234  str2=1234abcd  请按任意键继续. . .  */



指针经典话语:

1,指针指向谁,就把谁的地址赋给指针;

2,指针变量 和 它指向的内存空间变量是两个不同的概念

3,理解指针的关键是内存,没有内存哪里来的指针


变量的本质是一个固定大小的数据块,变量名就是数据块的编号


内存的使用范围:

main函数可以在栈分配内存/堆分配内存/全局分配内存,可以给子函数使用

子函数在栈分配的内存不能给主函数使用,但是堆内存与全局变量是可以给main使用


编译器会为每个程序分配一个内存4区,主函数与子函数公用这个内存4区


建立正确程序运行内存布局图是学好C的关键!


 


指针铁律1:指针是一种数据类型

1)指针也是一种变量,占有内存空间,用来保存内存地址

2)*p 操作内存;

3)*就像一把钥匙,通过一个地址(&a),去修改a变量的标示的内存空间

4)不断的给指针赋值,相当于不停的改变指针的指向。

5) 指针是一种数据类型,是指它指向内存空间的数据类型

指针铁律1:间接赋值(*p) 是指针存在的最大意义





向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI