91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C 提高2 間接賦值(*p) 是指針存在的最大意義

發布時間:2020-06-12 09:34:53 來源:網絡 閱讀:802 作者: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

武威市| 福海县| 闻喜县| 平罗县| 林口县| 镇原县| 日照市| 舒城县| 丹寨县| 和硕县| 郁南县| 鲁山县| 永和县| 祁连县| 禹城市| 岢岚县| 景洪市| 淳安县| 肃北| 滕州市| 河间市| 景谷| 长泰县| 潞西市| 宜兴市| 应城市| 拉萨市| 富蕴县| 平陆县| 宝山区| 开封市| 随州市| 紫金县| 永州市| 南澳县| 佛冈县| 隆安县| 资溪县| 启东市| 拜泉县| 金平|