国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C生萬物 | 從淺入深理解指針【第一部分】

這篇具有很好參考價(jià)值的文章主要介紹了C生萬物 | 從淺入深理解指針【第一部分】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

C生萬物 | 從淺入深理解指針【第一部分】

一、內(nèi)存和地址

1.1 內(nèi)存

  • 在講內(nèi)存和地址之前,我們想有個(gè)生活中的案例:

  • 假設(shè)有一棟宿舍樓,把你放在樓里,樓上有100個(gè)房間,但是房間沒有編號(hào),你的一個(gè)朋友來找你玩,如果想找到你,就得挨個(gè)房子去找,這樣效率很低,但是我們?nèi)绻鶕?jù)樓層和樓層的房間的情況,給每個(gè)房間編上號(hào),如:

    • 一樓:101,102,103…
    • 二樓:201,202,203…

有了房間號(hào),如果你的朋友得到房間號(hào),就可以快速的找房間,找到你。

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 生活中,每個(gè)房間有了房間號(hào),就能提高效率,能快速的找到房間。

如果把上面的例子對(duì)照到計(jì)算中,又是怎么樣呢?

  • 我們知道計(jì)算上CPU(中央處理器)在處理數(shù)據(jù)的時(shí)候,需要的數(shù)據(jù)是在內(nèi)存中讀取的,處理后的數(shù)據(jù)也會(huì)放回內(nèi)存中,那我們買電腦的時(shí)候,電腦上內(nèi)存是8GB/16GB/32GB等,那這些內(nèi)存空間如何高效的管理呢?

其實(shí)也是把內(nèi)存劃分為一個(gè)個(gè)的內(nèi)存單元,每個(gè)內(nèi)存單元的大小取1個(gè)字節(jié)。

  • 計(jì)算機(jī)中常見的單位(補(bǔ)充):
  • 一個(gè)比特位可以存儲(chǔ)一個(gè)2進(jìn)制的位1或者0
bit - 比特位
byte - 字節(jié)
KB
MB
GB
TB
PB
1byte = 8bit
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
  • 其中,每個(gè)內(nèi)存單元,相當(dāng)于一個(gè)學(xué)生宿舍,一個(gè)人字節(jié)空間里面能放8個(gè)比特位,就好比同學(xué)們住的八人間,每個(gè)人是一個(gè)比特位。
  • 每個(gè)內(nèi)存單元也都有一個(gè)編號(hào)(這個(gè)編號(hào)就相當(dāng)于宿舍房間的門牌號(hào)),有了這個(gè)內(nèi)存單元的編號(hào),CPU就可以快速找到一個(gè)內(nèi)存空間。
  • 生活中我們把門牌號(hào)也叫地址,在計(jì)算機(jī)中我們把內(nèi)存單元的編號(hào)也稱為地址。C語言中給地址起了新的名字叫:指針。

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 所以我們可以理解為:內(nèi)存單元的編號(hào) == 地址 == 指針

1.2 究竟該如何理解編址

  • CPU訪問內(nèi)存中的某個(gè)字節(jié)空間,必須知道這個(gè)字節(jié)空間在內(nèi)存的什么位置,而因?yàn)閮?nèi)存中字節(jié)很多,所以需要給內(nèi)存進(jìn)行編址(就如同宿舍很多,需要給宿舍編號(hào)一樣)。
  • 計(jì)算機(jī)中的編址,并不是把每個(gè)字節(jié)的地址記錄下來,而是通過硬件設(shè)計(jì)完成的。鋼琴、吉他面沒有寫上“都瑞咪發(fā)嗦啦”這樣的信息,但演奏者照樣能夠準(zhǔn)確找到每一個(gè)琴弦的每一個(gè)位置,這是為何?因?yàn)橹圃焐桃呀?jīng)在樂器硬件層面上設(shè)計(jì)好了,并且所有的演奏者都知道。本質(zhì)是一種約定出來的共識(shí)!硬件編址也是如此~~

  • 首先,必須理解,計(jì)算機(jī)內(nèi)是有很多的硬件單元,而硬件單元是要互相協(xié)同工作的。所謂的協(xié)同,至少相互之間要能夠進(jìn)行數(shù)據(jù)傳遞。但是硬件與硬件之間是互相獨(dú)立的,那么如何通信呢?答案很簡單,用"線"連起來。而CPU和內(nèi)存之間也是有大量的數(shù)據(jù)交互的,所以,兩者必須也用線連起來。不過,我們今天關(guān)心一組線,叫做地址總線。

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 我們可以簡單理解,32位機(jī)器有32根地址總線,每根線只有兩態(tài),表示0,1【電脈沖有無】,那么一根線,就能表示2種含義,2根線就能表示4種含義,依次類推。32根地址線,就能表示2^32種含義,每一種含義都代表一個(gè)地址。地址信息被下達(dá)給內(nèi)存,在內(nèi)存上,就可以找到該地址對(duì)應(yīng)的數(shù)據(jù),將數(shù)據(jù)在通過數(shù)據(jù)總線傳入CPU內(nèi)寄存器。

二、指針變量和地址

2.1 取地址操作符(&)

理解了內(nèi)存和地址的關(guān)系,我們再回到C語言,在C語言中創(chuàng)建變量其實(shí)就是向內(nèi)存申請(qǐng)空間,比如:

  • 下面這段代碼變量創(chuàng)建的本質(zhì)是什么?
int main() 
{
	int a = 10;
	return 0;
}
  • 變量創(chuàng)建的本質(zhì)是:在內(nèi)存上開辟空間~~
    要向內(nèi)存申請(qǐng)4個(gè)字節(jié)的空間,存放數(shù)據(jù)0

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 比如,上述的代碼就是創(chuàng)建了整型變量a,內(nèi)存中申請(qǐng)4個(gè)字節(jié),用于存放整數(shù)10,其中每個(gè)字節(jié)都有地址,上圖中4個(gè)字節(jié)的地址分別是:
0x005FFC54  0a  
0x005FFC55  00  
0x005FFC56  00  
0x005FFC57  00  

那我們?nèi)绾文艿玫絘的地址呢?

  • 這里就得學(xué)習(xí)一個(gè)操作符(&)-取地址操作符
#include <stdio.h>
int main() {
	int a = 10;
	&a;//取出a的地址
	printf("%p\n", &a);
	return 0;
}
  • 對(duì)于a來說,我們那到的是a所占4個(gè)字節(jié)的第一個(gè)地址(地址較小的那個(gè)字節(jié)的地址)

按照我畫圖的例子,會(huì)打印處理:005FFC54

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 雖然整型變量占用4個(gè)字節(jié),我們只要知道了第一個(gè)字節(jié)地址,順藤摸瓜訪問到4個(gè)字節(jié)的數(shù)據(jù)也是可
    行的。

三、指針變量和解引用操作符(*)

3.1 指針變量

  • 那我們通過取地址操作符(&)拿到的地址是一個(gè)數(shù)值,比如:0x006FFD70,這個(gè)數(shù)值有時(shí)候也是需要存儲(chǔ)起來,方便后期再使用的,那我們把這樣的地址值存放在哪里呢?答案是:指針變量中。

  • 比如:

int main() {
	int a = 10;
	int* pa = &a;//取出a的地址并存儲(chǔ)到指針變量pa中
	return 0;
}
  • 其中pa叫做指針變量~~,因?yàn)槭谴娣胖羔樀淖兞浚越凶鲋羔樧兞?/li>
  • 指針變量也是一種變量,這種變量就是用來存放地址的,存放在指針變量中的值都會(huì)理解為地址。

3.2 如何拆解指針類型

  • 我們看到pa的類型是int* ,我們該如何理解指針的類型呢?
int a = 10;
int* pa = &a;
  • 這里pa左邊寫的是int*,*是在說明pa是指針變量,而前面的int是在說明pa指向的是整型(int)類型的對(duì)象。

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 那如果有一個(gè)char類型的變量ch,ch的地址,要放在什么類型的指針變量中呢?
char ch = 'w';
pc = &ch;//pc 的類型怎么寫呢?
  • 既然是char類型的變量,那肯定就要放在char類型的指針變量里~~
char ch = 'w';
char* pc = &ch;

3.3 解引用操作符

  • 我們將地址保存起來,未來是要使用的,那怎么使用呢?
    在現(xiàn)實(shí)生活中,我們使用地址要找到一個(gè)房間,在房間里可以拿去或者存放物品。

  • C語言中其實(shí)也是一樣的,我們只要拿到了地址(指針),就可以通過地址(指針)找到地址(指針)指向的對(duì)象,這里必須學(xué)習(xí)一個(gè)操作符叫解引用操作符(*)。

#include <stdio.h>

int main()
{
	int a = 100;
	int* pa = &a;
	*pa = 0;
	return 0;
}
  • 上面代碼中第7行就使用了解引用操作符, *pa 的意思就是通過pa中存放的地址,找到指向的空間,pa其實(shí)就是a變量了;所以pa = 0,這個(gè)操作符是把a(bǔ)改成了0.有同學(xué)肯定在想,這里如果目的就是把a(bǔ)改成0的話,寫成a = 0; 不就完了,為啥非要使用指針呢?
  • 其實(shí)這里是把a(bǔ)的修改交給了pa來操作,這樣對(duì)a的修改,就多了一種的途徑,寫代碼就會(huì)更加靈活,后期慢慢就能理解了。

四、指針變量的大小

  • 前面的內(nèi)容我們了解到,32位機(jī)器假設(shè)有32根地址總線,每根地址線出來的電信號(hào)轉(zhuǎn)換成數(shù)字信號(hào)后是1或者0,那我們把32根地址線產(chǎn)生的2進(jìn)制序列當(dāng)做一個(gè)地址,那么一個(gè)地址就是32個(gè)bit位,需要4個(gè)字節(jié)才能存儲(chǔ)。
  • 如果指針變量是用來存放地址的,那么指針變的大小就得是4個(gè)字節(jié)的空間才可以。
  • 同理64位機(jī)器,假設(shè)有64根地址線,一個(gè)地址就是64個(gè)二進(jìn)制位組成的二進(jìn)制序列,存儲(chǔ)起來就需要
  • 8個(gè)字節(jié)的空間,指針變的大小就是8個(gè)字節(jié)。

  • 接下來我們再看看下面這個(gè)~~
int main()
{
	int num = 10;
	int* p = &num;
	
	char ch = 'w';
	char* pc = &ch;

	printf("%zd\n", sizeof(p));
	printf("%zd\n", sizeof(pc));
	return 0;
}
  • 我們這里是x86環(huán)境下,猜猜這里這個(gè)ppc的大小是多少?p是4個(gè)字節(jié)?pc是1個(gè)字節(jié)?

  • 讓我們來看看~~
    C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到,都是4個(gè)字節(jié),指針變量的大小是固定的,不要以為char*類型的就小,看不起char*類型的指針~~

x86環(huán)境下為什么char*的指針變量和int*的指針變量都是4個(gè)字節(jié)呢?

  • 指針變量是干什么呢?是為了存放地址的

  • 那指針變量的大小是取決于存放一個(gè)地址需要多大的空間?。。?/p>

  • 地址都是32個(gè)0/1組成的二進(jìn)制序列的話,那么存放這個(gè)地址需要的空間的大小就是4個(gè)字節(jié),所以指針變量的大小都是4個(gè)字節(jié)~~

  • 同樣x64環(huán)境,64根地址線,地址就是64個(gè)0/1組成的二進(jìn)制序列,存放這樣的地址,需要8個(gè)字節(jié),所以指針變量的大小就是8個(gè)字節(jié)~~

  • 如果不相信,我們在VS中試一下~~

#include <stdio.h>
//指針變量的大小取決于地址的大小
//32位平臺(tái)下地址是32個(gè)bit位(即4個(gè)字節(jié))
//64位平臺(tái)下地址是64個(gè)bit位(即8個(gè)字節(jié))
int main()
{
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(double*));
	return 0;
}
  • 32位下:

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 64位下:

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 俗話說,不要在門縫里看人,把人看扁了
  • 今天,我要告訴你,不要在門縫里看指針,把指針看扁了~~

結(jié)論:

  • 32位平臺(tái)下地址是32個(gè)bit位,指針變量大小是4個(gè)字節(jié)
  • 64位平臺(tái)下地址是64個(gè)bit位,指針變量大小是8個(gè)字節(jié)
  • 注意指針變量的大小和類型是無關(guān)的,只要指針類型的變量,在相同的平臺(tái)下,大小都是相同的。

4.1 指針變量類型的意義

  • 指針變量的大小和類型無關(guān),只要是指針變量,在同一個(gè)平臺(tái)下,大小都是一樣的,為什么還要有各種各樣的指針類型呢?

  • 其實(shí)指針類型是有特殊意義的,我們接下來繼續(xù)學(xué)習(xí)~~

4.2 指針的解引用

  • 我們來看下面的兩段代碼,通過調(diào)試來進(jìn)行分析,觀察內(nèi)存的變化~~

代碼一:

#include <stdio.h>
int main()
{
	int n = 0x11223344;
	int* pi = &n;
	*pi = 0;
	return 0;
}

代碼二:

#include <stdio.h>
int main()
{
	int n = 0x11223344;
	char* pc = &n;
	*pc = 0;
	return 0;
}
  • 我們按鍵盤上的F10,如果有的同學(xué)是筆記本,就在筆記本上按Fn+F10,開始調(diào)試
  • 打開調(diào)試->窗口->內(nèi)存->

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 這個(gè)時(shí)候我們發(fā)現(xiàn),怎么是倒著存的?不應(yīng)該是正的存嗎,這里就要涉及到一個(gè)概念,大小端存儲(chǔ)如果還有同學(xué)不知道的話可以看看這個(gè)章節(jié)->C生萬物 | 深度挖掘數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的存儲(chǔ)
  • 我們回歸正題~~
  • 我們把這個(gè)n的地址取出來放到pi變量里,然后解引用,把n的值改為0,我們可以看一下~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到,4個(gè)字節(jié)全部改為了0~~

現(xiàn)在再來看第二個(gè)代碼~~

  • 我們可以看到我將n的地址放到char*類型的變量里,那能不能放的下?
  • 答案是能?。。倓偩驼f過,指針變量都是4個(gè)字節(jié),為什么放不下~~
  • 然后我們繼續(xù)看,*pc = 0,我們這個(gè)是修改的幾個(gè)字節(jié)?

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 我們可以看到,它只修改了一個(gè)字節(jié),因?yàn)槭?code>char*的指針變量

結(jié)論:

  1. 指針類型是有意義的
  2. 指針類型是決定了指針在解引用操作時(shí)的權(quán)限,也就是一次解引用訪問幾個(gè)字節(jié),char*類型的指針解引用訪問1個(gè)字節(jié),int*類型的指針一次訪問4個(gè)字節(jié)

4.3 指針±整數(shù)

  • 我們先來看下面這一段代碼~~
#include <stdio.h>
int main()
{
	int n = 0x11223344;
	int* p = &n;
	char* pc = &n;

	printf("p = %p\n", p);
	printf("p + 1 = %p\n", p + 1);

	printf("pc = %p\n", pc);
	printf("pc + 1 = %p\n", pc + 1);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 我們可以看出, char* 類型的指針變量+1跳過1個(gè)字節(jié), int* 類型的指針變量+1跳過了4個(gè)字節(jié)。
  • 這就是指針變量的類型差異帶來的變化。

結(jié)論:

  1. 指針類型是有意義的
  2. 指針類型決定了指針進(jìn)行+1/-1操作的時(shí)候一次跳過幾個(gè)字節(jié)
  3. 指針的類型決定了指針向前或者向后走一步有多大(距離)。

那有的同學(xué)會(huì)問,指針類型這些特點(diǎn),怎么是使用呢?

  • 我們之前一個(gè)數(shù)組是用數(shù)組的下標(biāo)來訪問的,今天我們就用指針的方式訪問~~

我們先來回憶一下數(shù)組的方式~~

int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//下標(biāo)的方式
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++) {
		printf("%d ", arr[i]);
	}
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到,我們已經(jīng)將數(shù)組中的元素已經(jīng)打印出來了~~

我們再用指針的方式來訪問~~

  • 我們將arr[0]的地址放入了指針p中,然后再通過for循環(huán)中*p找到arr每個(gè)的元素,那找到一個(gè)元素,還想找下一個(gè)元素怎么辦?那就要加1,因?yàn)閜是整形指針,+1跳過4個(gè)字節(jié),正好找到下一個(gè)元素
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//下標(biāo)的方式
	int sz = sizeof(arr) / sizeof(arr[0]);
	//int i = 0;
	//for (i = 0; i < sz; i++) {
	//	printf("%d ", arr[i]);
	//}

	//指針的方式
	int i = 0;
	int* p = &arr[0];
	for (i = 0; i < sz; i++) {
		printf("%d ", *p);
		p = p + 1;
	}
	return 0;
}
  • 我們可以看到,也全部訪問到了~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 那有的同學(xué)回說,我不想另外讓p+1,我直接*(p+i),這樣可以嗎?當(dāng)然可以!??!
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//指針的方式
	int i = 0;
	int* p = &arr[0];
	for (i = 0; i < sz; i++) {
		printf("%d ", *(p + i));
	}
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 如果不懂的話,我們進(jìn)行畫圖理解
    C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

相信看完了上面,你對(duì)指針類型有一個(gè)對(duì)應(yīng)理解~~

五、const修飾指針

  • 變量是可以修改的,如果把變量的地址交給一個(gè)指針變量,通過指針變量的也可以修改這個(gè)變量。
#include<stdio.h>
int main() {
	int n = 100;
	n = 200;

	printf("%d\n", n);
	return 0;
}
  • 但是如果我們希望一個(gè)變量加上一些限制,不能被修改,怎么做呢?這就是const的作用。
int main() {
	const int n = 100;
	n = 200;//err

	printf("%d\n", n);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 上述代碼中n是不能被修改的,其實(shí)n本質(zhì)是變量,只不過被const修飾后,在語法上加了限制,只要我們在代碼中對(duì)n就行修改,就不符合語法規(guī)則,就報(bào)錯(cuò),致使沒法直接修改n。
  • 但是如果我們繞過n,使用n的地址,去修改n就能做到了,雖然這樣做是在打破語法規(guī)則。
  • 那有人這樣想,這樣不能修改,那我繞個(gè)彎,把n的地址取出來,交給一個(gè)指針變量p,然后進(jìn)行修改~~
int main() {
	const int n = 100;
	int* p = &n;
	*p = 200;

	printf("%d\n", n);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 哎!它怎么修改了?就比如說有個(gè)門,門鎖上了,看見有個(gè)窗戶,我從窗戶進(jìn)去了,這個(gè)行為就是鉆窗戶行為~~
  • 這里一個(gè)確實(shí)修改了,但是我們還是要思考一下,為什么n要被const修飾呢?就是為了不能被修改,如果p拿到n的地址就能修改n,這樣就打破了const的限制,這是不合理的,所以應(yīng)該讓p拿到n的地址也不能修改n,那接下來怎么做呢?

5.1 const修飾指針變量

const修飾指針有兩種情況:

  1. const放在*的左邊
  2. const放在*的右邊
  • 首先我們先將const放在*的左邊~~
int main() {
	int m = 100;
	int n = 10;

	const int* p = &n;
	*p = 0;

	p = &m;

	printf("%d\n", n);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 這里可以看到p指向的值不能被修改
  • p變量還是可以被修改的~~

  • 然后我們先將const放在*的左邊~~
int main() {
	int m = 100;
	int n = 10;

	int* const p = &n;
	*p = 0;

	p = &m;

	printf("%d\n", n);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到p指向的對(duì)象可以被修改~~

結(jié)論:

  1. const如果放在*的左邊,修飾的是指針指向的內(nèi)容,保證指針指向的內(nèi)容不能通過指針來改變。但是指針變量本身的內(nèi)容可變。
  2. const如果放在*的右邊,修飾的是指針變量本身,保證了指針變量的內(nèi)容不能修改,但是指針指向的內(nèi)容,可以通過指針改變。

  • 那有的同學(xué)說我這樣放,可不可以?可以?。?!
int const *  p = &n;
int *const  p = &n;
  • 這兩種方法都是可以的,我們只是關(guān)注的是const放在*左邊還是右邊

六、指針運(yùn)算

6.1 指針± 整數(shù)

  • 因?yàn)閿?shù)組在內(nèi)存中是連續(xù)存放的,只要知道第一個(gè)元素的地址,順藤摸瓜就能找到后面的所有元素。
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

#include <stdio.h>
//指針+- 整數(shù)
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//p+i 這里就是指針+整數(shù)
	}
	return 0;
}
  • 接下來我們就調(diào)試起來看一看

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到已經(jīng)放進(jìn)去了

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 這里p+i就訪問到每一個(gè)元素了~~

6.2 指針-指針

  • 指針-指針是有前提的,指針和指針兩個(gè)指針的指向同一塊空間
  • 我們先來看下面的這個(gè)一個(gè)代碼,輸出的結(jié)果是多少?
int main() {
	int arr[10] = { 0 };
	int ret = &arr[9] - &arr[0];

	printf("%d", ret);

	return 0;
 }
  • 答案是9~~,我們來分析一下:

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 也可以這樣理解,&arr[0]+9—>>>&arr[9]

  • 結(jié)論: 指針-指針得到的絕對(duì)值,是指針和指針之間元素的個(gè)數(shù)


  • 那有的同學(xué)說,那這個(gè)有什么用呢?
  • 還記得有一個(gè)函數(shù)strlen嗎?
  • strlen的功能是求字符串長度,如果有同學(xué)不了解這個(gè)函數(shù)的話可以去cplusplus網(wǎng)站上看一下
  • 我們來看一下怎么使用
int main() 
{
	char arr[] = "abcdef";
	int len = strlen(arr);

	printf("%d\n", len);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到它已經(jīng)求出字符串長度了~~
  • 我們知道字符串的結(jié)束標(biāo)志是\0,讓我求長度,我就統(tǒng)計(jì)\0之前出現(xiàn)字符的個(gè)數(shù)

  • 那我們現(xiàn)在自己模擬實(shí)現(xiàn)一下這個(gè)函數(shù)~~
  • 我們這里寫成my_strlen,我們把數(shù)組傳參,然后形參以指針接收,指針指向了數(shù)組首元素的地址,然后我們定義個(gè)計(jì)數(shù)器count,如果p!=\0,count++,p++,最后返回count的個(gè)數(shù)~~
int my_strlen(char* p)
{
	int count = 0;
	while (*p != '\0')
	{
		count++;
		p++;
	}
	return count;
}


int main() 
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);

	printf("%d\n", len);
	return 0;
}
  • 可以看到也統(tǒng)計(jì)出來個(gè)數(shù)了~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)


  • 我們再寫出另一個(gè)版本,接下來繼續(xù)看~~
  • 我們知道指針減去指針得到的是元素之間的個(gè)數(shù)
  • 首先我記錄一下起始位置,讓p++,一直找到\0為止,最后返回p-s就得到了元素的個(gè)數(shù)~~
  • 我們來看一下代碼和結(jié)果~~
#include <stdio.h>
int my_strlen(char* s)
{
	char* p = s;
	while (*p != '\0')
		p++;
	return p - s;
}
int main()
{
	printf("%d\n", my_strlen("abc"));
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

明白了上面的內(nèi)容,我們再來將一個(gè)指針的關(guān)系運(yùn)算~~


6.3 指針的關(guān)系運(yùn)算

  • 所謂的關(guān)系運(yùn)算,就是比較大小
  • 我們來看一下例子~~
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz) //指針的大小比較
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}
  • 這里我們比較的是兩個(gè)地址的大小關(guān)系~~
  • 我們可以看到,也是可以打印出來的~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

七、野指針

  • 概念: 野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒有明確限制的)

7.1 野指針成因

指針未初始化:

#include <stdio.h>
int main()
{
	int* p;//局部變量指針未初始化,默認(rèn)為隨機(jī)值
	*p = 20;
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到這里報(bào)了錯(cuò),如果你有看過我寫的函數(shù)的棧幀創(chuàng)建與銷毀就明白了,局部變量不初始化默認(rèn)里面放的是cccccccc
  • 所以一個(gè)局部變量不初始化的話,會(huì)得到一個(gè)隨機(jī)值~~
  • 而隨便的一個(gè)地址,能解引用嗎?不能?。?!
  • 一塊空間你要想使用,你需要先申請(qǐng)拿到這塊空間

指針越界訪問:

  • 我們先來看代碼
#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = &arr[0];
	int i = 0;
	for (i = 0; i <= 11; i++)
	{
		//當(dāng)指針指向的范圍超出數(shù)組arr的范圍時(shí),p就是野指針
		*(p++) = i;
	}
	return 0;
}
  • 我們這里的p++是先執(zhí)行的,而p++是先使用后++

  • 我們這里可以看到,我把arr[0]的地址放入了*p指針變量,然后我們進(jìn)行遍歷賦值,那我們這里判斷條件是不是就越界訪問了,超出了數(shù)組的范圍,當(dāng)指針指向的范圍超出數(shù)組arr的范圍時(shí),p就是野指針,這是很危險(xiǎn)的~~

  • 我們這里還可以調(diào)試一下看看~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 可以看到,數(shù)組arr造到了破壞,而越界訪問的內(nèi)容也修改了,如此可見,這多么的危險(xiǎn)?。?!

7.2 指針指向的空間釋放

  • 我們先來看一下下面的代碼~~
#include <stdio.h>
int* test()
{
	int n = 100;
	return &n;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}
  • 這里創(chuàng)建了一個(gè)函數(shù)test(),返回一個(gè)地址,既然這個(gè)函數(shù)返回的是一個(gè)地址,那我用一個(gè)指針來接收,然后*p這個(gè)地址
  • 這個(gè)n在出這個(gè)函數(shù)的時(shí)候被銷毀了,這就會(huì)造成指針指向的空間釋放~~

八、如何規(guī)避野指針

8.1 指針初始化

  • 如果明確知道指針指向哪里就直接賦值地址
  • 如果不知道指針應(yīng)該指向哪里,可以給指針賦值NULL

什么意思呢,我們用代碼來說~~

  • 這里的p非常明確的指向了a,直接賦值~~
int main() 
{
	int a = 10;
	int* p = &a;
	return 0;
}
  • 我們這里假設(shè)在這里創(chuàng)建了個(gè)ptr,我現(xiàn)在不用,但我可以在后面才會(huì)用,但是這個(gè)指針變量不能空著,這個(gè)時(shí)候我們要給他初始化NULL
int main() 
{
	int a = 10;
	int* p = &a;
	int* ptr = NULL;
	return 0;
}
  • NULL是什么呢?本質(zhì)上就是空指針,我們這個(gè)時(shí)候可以右鍵,轉(zhuǎn)到定義里看一下

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 那有的同學(xué)會(huì)說,那我直接給他賦值為0,可不可以呢?本質(zhì)上是可以的,但是,當(dāng)我們賦值為0了,有的時(shí)候會(huì)以為是一個(gè)整數(shù),而我們賦值為NULL的時(shí)候,那就很明顯了,一看就是空~~

  • NULL 是C語言中定義的一個(gè)標(biāo)識(shí)符常量,值是0,0也是地址,這個(gè)地址是無法使用的,讀寫該地址會(huì)報(bào)錯(cuò)。

  • 這里我們也可以看到~~

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

8.2 小心指針越界

  • 一個(gè)程序向內(nèi)存申請(qǐng)了哪些空間,通過指針也就只能訪問哪些空間,不能超出范圍訪問,超出了就是越界訪問
  • 這個(gè)誰都幫不了你,只能自己小心,不要越界~~
  • 一個(gè)程序員想寫bug,誰都攔不住~~

8.3 指針變量不再使用時(shí),及時(shí)置NULL,指針使用之前檢查有效性

  • 當(dāng)指針變量指向一塊區(qū)域的時(shí)候,我們可以通過指針訪問該區(qū)域,后期不再使用這個(gè)指針訪問空間的時(shí)候,我們可以把該指針置為NULL。因?yàn)榧s定俗成的一個(gè)規(guī)則就是:只要是NULL指針就不去訪問,同時(shí)使用指針之前可以判斷指針是否為NULL。
  • 我們可以把野指針想象成野狗,野狗放任不管是非常危險(xiǎn)的,所以我們可以找一棵樹把野狗拴起來,就相對(duì)安全了,給指針變量及時(shí)賦值為NULL,其實(shí)就類似把野狗栓前來,就是把野指針暫時(shí)管理起來。
  • 不過野狗即使拴起來我們也要繞著走,不能去挑逗野狗,有點(diǎn)危險(xiǎn);對(duì)于指針也是,在使用之前,我們也要判斷是否為NULL,看看是不是被拴起來起來的野狗,如果是不能直接使用,如果不是我們再去使用。

  • 下面我們來看一段代碼~~
  • 這里我們創(chuàng)建了一個(gè)數(shù)組,然后用指針遍歷這個(gè)數(shù)組,當(dāng)遍歷完后,指針已經(jīng)指向了10的后面,指向了不屬于我們的空間
  • 假設(shè)暫時(shí)不再使用p了,為了安全,我們可以把p賦值為NULL
  • 如果后面還會(huì)用到這個(gè)指針,我們再把這個(gè)p賦值,我們還可以再進(jìn)行判斷是否為NULL
int main()
{
	int arr[10] = { 1,2,3,4,5,67,7,8,9,10 };
	int* p = &arr[0];
	for (int i = 0; i < 10; i++)
	{
		*(p++) = i;
	}
	//此時(shí)p已經(jīng)越界了,可以把p置為NULL
	p = NULL;
	//下次使用的時(shí)候,判斷p不為NULL的時(shí)候再使用
	//...
	p = &arr[0];//重新讓p獲得地址
	if (p != NULL) //判斷
	{
		//...
	}
	return 0;
}

8.4 避免返回局部變量的地址

  • 我們來看下面這一段代碼
  • 首先我們先調(diào)用了一下test函數(shù),函數(shù)里創(chuàng)建了個(gè)數(shù)組,數(shù)組是局部變量,而我們返回了這個(gè)數(shù)組的地址,我們使用了一個(gè)指針變量p來接收,當(dāng)test函數(shù)返回的時(shí)候局部變量已經(jīng)被操作系統(tǒng)回收了,這就會(huì)造成野指針,如果有看過函數(shù)的棧幀的創(chuàng)建與銷毀的話就明白了
  • 返回??臻g地址的問題,很容易造成野指針的問題~~
int* test()
{
	//局部變量
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//.....
	return arr;
}

int main()
{
	int* p = test();//p就是野指針
	return 0;
}

九、assert斷言

  • assert.h 頭文件定義了宏assert() ,用于在運(yùn)行時(shí)確保程序符合指定條件,如果不符合,就報(bào)錯(cuò)終止運(yùn)行。這個(gè)宏常常被稱為“斷言”。
assert(p != NULL);

  • 上面代碼在程序運(yùn)行到這一行語句時(shí),驗(yàn)證變量p是否等于NULL 。如果確實(shí)不等于NULL ,程序繼續(xù)運(yùn)行,否則就會(huì)終止運(yùn)行,并且給出報(bào)錯(cuò)信息提示。
  • 我們可以看到,什么都不會(huì)發(fā)生~~
#include <assert.h>

int main()
{
	int a = 10;
	int* p = &a;
	assert(p != NULL);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 當(dāng)我們賦值為了一個(gè)空指針時(shí),可以看到會(huì)報(bào)錯(cuò)誤
  • 通過這樣一個(gè)方式就可以攔住他~~
#include <assert.h>

int main()
{
	int a = 10;
	int* p = NULL;
	assert(p != NULL);
	return 0;
}

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • assert() 宏接受一個(gè)表達(dá)式作為參數(shù)。如果該表達(dá)式為真(返回值非零), assert()不會(huì)產(chǎn)生任何作用,程序繼續(xù)運(yùn)行。如果該表達(dá)式為假(返回值為零), assert() 就會(huì)報(bào)錯(cuò),在標(biāo)準(zhǔn)錯(cuò)誤流stderr 中寫入一條錯(cuò)誤信息,顯示沒有通過的表達(dá)式,以及包含這個(gè)表達(dá)式的文件名和行號(hào)。
  • assert() 的使用對(duì)程序員是非常友好的,使用assert() 有幾個(gè)好處:它不僅能自動(dòng)標(biāo)識(shí)文件和出問題的行號(hào),還有一種無需更改代碼就能開啟或關(guān)閉assert() 的機(jī)制。如果已經(jīng)確認(rèn)程序沒有問題,不需要再做斷言,就在#include <assert.h> 語句的前面,定義一個(gè)宏NDEBUG 。
#define NDEBUG
#include <assert.h>
  • 然后,重新編譯程序,編譯器就會(huì)禁用文件中所有的assert() 語句。如果程序又出現(xiàn)問題,可以移除這條#define NDBUG 指令(或者把它注釋掉),再次編譯,這樣就重新啟用了assert() 語句。

  • assert() 的缺點(diǎn)是,因?yàn)橐肓祟~外的檢查,增加了程序的運(yùn)行時(shí)間。

  • 一般我們可以在debug中使用,在release版本中選擇禁用assert就行,在VS這樣的集成開發(fā)環(huán)境中,在release版本中,直接就是優(yōu)化掉了。這樣在debug版本寫有利于程序員排查問題,在release版本不影響用戶使用時(shí)程序的效率。

十、指針的使用和傳址調(diào)用

一直叫傳值調(diào)用,一種叫傳址調(diào)用,接下來我們繼續(xù)看~~

10.1 傳址調(diào)用

  • 學(xué)習(xí)指針的目的是使用指針解決問題,那什么問題,非指針不可呢?
    例如:寫一個(gè)函數(shù),交換兩個(gè)整型變量的值
  • 一番思考后,我們可能寫出這樣的代碼:
#include <stdio.h>
void Swap1(int x, int y)
{
	int tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交換前:a=%d b=%d\n", a, b);
	Swap1(a, b);
	printf("交換后:a=%d b=%d\n", a, b);
	return 0;
}

當(dāng)我們運(yùn)行代碼,結(jié)果如下:

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 這里怎么沒有達(dá)到交換的效果?我們來調(diào)試看一下
  • 我們可以看到只有x和y交換了,而a和b沒有交換

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 我們發(fā)現(xiàn)在main函數(shù)內(nèi)部,創(chuàng)建了a和b,a的地址是0x0039f9f0,b的地址是0x0039f9e4,在調(diào)用Swap1函數(shù)時(shí),將a和b傳遞給了Swap1函數(shù),在Swap1函數(shù)內(nèi)部創(chuàng)建了形參x和y接收a和b的值,但是x的地址是0x0039f90c,y的地址是0x0039f910,x和y確實(shí)接收到了a和b的值,不過x的地址和a的地址不一樣,y的地址和b的地址不一樣,相當(dāng)于x和y是獨(dú)立的空間,那么在Swap1函數(shù)內(nèi)部交換x和y的值,自然不會(huì)影響a和b,當(dāng)Swap1函數(shù)調(diào)用結(jié)束后回到main函數(shù),a和b的沒法交換。Swap1函數(shù)在使用的時(shí)候,是把變量本身直接傳遞給了函數(shù),這種調(diào)用函數(shù)的方式我們之前在函數(shù)的時(shí)候就知道了,這種叫傳值調(diào)用。

結(jié)論: 實(shí)參傳遞給形參的時(shí)候,形參會(huì)單獨(dú)創(chuàng)建一份臨時(shí)空間來接收實(shí)參,對(duì)形參的修改不影響實(shí)參。所以Swap是失敗的了。


10.2 傳址調(diào)用

  • 那怎么辦呢?
  • 我們現(xiàn)在要解決的就是當(dāng)調(diào)用Swap函數(shù)的時(shí)候,Swap函數(shù)內(nèi)部操作的就是main函數(shù)中的a和b,直接將a和b的值交換了。那么就可以使用指針了,在main函數(shù)中將a和b的地址傳遞給Swap函數(shù),Swap函數(shù)里邊通過地址間接的操作main函數(shù)中的a和b就好了。
#include <stdio.h>
void Swap2(int* px, int* py)
{
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交換前:a=%d b=%d\n", a, b);
	Swap2(&a, &b);
	printf("交換后:a=%d b=%d\n", a, b);
	return 0;
}

首先看輸出結(jié)果:

C生萬物 | 從淺入深理解指針【第一部分】,C生萬物,c語言,開發(fā)語言,1024程序員節(jié)

  • 我們可以看到實(shí)現(xiàn)成Swap2的方式,順利完成了任務(wù),這里調(diào)用Swap2函數(shù)的時(shí)候是將變量的地址傳遞給了函數(shù),這種函數(shù)調(diào)用方式叫:傳址調(diào)用。

十一、strlen的模擬實(shí)現(xiàn)

  • 這個(gè)我們上面已經(jīng)實(shí)現(xiàn)過了,這次我們再寫的全一些~~
  • 我們創(chuàng)建了一個(gè)字符數(shù)組,要求出這個(gè)字符串的長度,我們寫一個(gè)my_strlen()
  • 它傳參傳的是數(shù)組首元素的地址,我們用一個(gè)*str的指針來接收,我們這個(gè)函數(shù)期望這個(gè)字符串來修改嗎?不期望,這里我們再加上一個(gè)const
  • 這里我們需要斷言str,確保指針的有效性
  • 現(xiàn)在str指向a的,當(dāng)str!='\0',str++,計(jì)數(shù)器也++,最后返回計(jì)數(shù)器~~
  • 求字符串的時(shí)候沒有負(fù)數(shù)吧,我們就可以設(shè)置成size_t
  • 現(xiàn)在軟件更加健壯了,也叫魯棒性~~

計(jì)數(shù)器方式

size_t my_strlen(const char* str)
{
	size_t count = 0;
	assert(str);
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	printf("%zd\n", len);
	return 0;
}

好了,指針的第一部分就到這里就結(jié)束了~~
如果有什么問題可以私信我或者評(píng)論里交流~~
感謝大家的收看,希望我的文章可以幫助到正在閱讀的你??????文章來源地址http://www.zghlxwxcb.cn/news/detail-714959.html

到了這里,關(guān)于C生萬物 | 從淺入深理解指針【第一部分】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 真正理解微軟Windows程序運(yùn)行機(jī)制——窗口機(jī)制(第一部分)

    真正理解微軟Windows程序運(yùn)行機(jī)制——窗口機(jī)制(第一部分)

    我是荔園微風(fēng),作為一名在IT界整整25年的老兵,今天說說Windows程序的運(yùn)行機(jī)制。經(jīng)常被問到MFC到底是一個(gè)什么技術(shù),為了解釋這個(gè)我之前還寫過帖子,但是很多人還是不理解。其實(shí)這沒什么,我在學(xué)生時(shí)代也被這個(gè)問題困繞過。而且那個(gè)時(shí)間學(xué)習(xí)資料沒有那么豐富,網(wǎng)上也

    2024年02月10日
    瀏覽(18)
  • 從淺入深掌握進(jìn)階結(jié)構(gòu)體(C語言)

    從淺入深掌握進(jìn)階結(jié)構(gòu)體(C語言)

    前言 這一期我們將繼續(xù)講解結(jié)構(gòu)體的知識(shí),還沒有看過上一期的小伙伴一定要趕緊去學(xué)習(xí)哦。 上一期,沖鴨! 那么話不多說我們開始今天的學(xué)習(xí)吧! 什么是結(jié)構(gòu)體的自引用呢?簡單來說就是自己裝自己(有點(diǎn)類似遞歸)。 那么是這樣自引用的么? 但是這樣寫好像有問題啊

    2024年02月03日
    瀏覽(21)
  • Golang面試題從淺入深高頻必刷「2023版」

    大家好,我是陽哥。 專注Go語言的學(xué)習(xí)經(jīng)驗(yàn)分享和就業(yè)輔導(dǎo)。 Go語言相比C++/Java等語言是優(yōu)雅且簡潔的,是我最喜愛的編程語言之一,它既保留了C++的高性能,又可以像Java,Python優(yōu)雅的調(diào)用三方庫和管理項(xiàng)目,同時(shí)還有接口,自動(dòng)垃圾回收和goroutine等讓人拍案叫絕的設(shè)計(jì)。

    2024年02月05日
    瀏覽(18)
  • # 從淺入深 學(xué)習(xí) SpringCloud 微服務(wù)架構(gòu)(二)模擬微服務(wù)環(huán)境(1)

    # 從淺入深 學(xué)習(xí) SpringCloud 微服務(wù)架構(gòu)(二)模擬微服務(wù)環(huán)境(1)

    段子手168 創(chuàng)建 artifactId 名為 spring_cloud_demo 的 maven 工程。 1)創(chuàng)建 子工程(子模塊) — 創(chuàng)建數(shù)據(jù)庫: create database shop; — 使用數(shù)據(jù)庫: use shop; — 創(chuàng)建數(shù)據(jù)表: — 插入數(shù)據(jù): insert into tb_product ( id , product_name , status , price , product_desc , caption , inventory ) values (1,‘iPhone 15 Pron’

    2024年04月25日
    瀏覽(24)
  • # 從淺入深 學(xué)習(xí) SpringCloud 微服務(wù)架構(gòu)(三)注冊中心 Eureka(3)

    # 從淺入深 學(xué)習(xí) SpringCloud 微服務(wù)架構(gòu)(三)注冊中心 Eureka(3)

    段子手168 Eureka Server 可以通過運(yùn)行多個(gè)實(shí)例并相互注冊的方式實(shí)現(xiàn)高可用部署, Eureka Server 實(shí)例會(huì)彼此增量地同步信息,從而確保所有節(jié)點(diǎn)數(shù)據(jù)一致。 事實(shí)上,節(jié)點(diǎn)之間相互注冊是 Eureka Server 的默認(rèn)行為。 1)修改 eureka_server 子工程(子模塊)中的 application.yml 文件 模擬兩個(gè)

    2024年04月26日
    瀏覽(22)
  • 數(shù)據(jù)結(jié)構(gòu) | 單鏈表SingleList【帶你從淺入深真正搞懂鏈表】

    數(shù)據(jù)結(jié)構(gòu) | 單鏈表SingleList【帶你從淺入深真正搞懂鏈表】

    寫在前面 很多粉絲經(jīng)常私信問我有關(guān) 指針、鏈表 相關(guān)的問題,也非常希望我出一篇有關(guān)鏈表的教學(xué),最近剛好也在整理有關(guān)單鏈表相關(guān)的知識(shí)點(diǎn),便作了此文,為大家講解有關(guān)單鏈表方面的各塊知識(shí)點(diǎn)。 本文考慮到閱讀者的水平和能力,內(nèi)容有深有淺,總體講解主要是 從

    2024年01月17日
    瀏覽(70)
  • 從淺入深了解.NET Core MVC 2.x全面教程【第二章】

    從淺入深了解.NET Core MVC 2.x全面教程【第二章】

    章節(jié) 第一章:https://www.cnblogs.com/kimiliucn/p/17611047.html 第二章:https://www.cnblogs.com/kimiliucn/p/17616708.html 1.診斷中間件 命名空間:Microsoft.AspNetCore.Diagnostics 報(bào)告信息并處理異常 2.診斷中間件 UseDeveloperExceptionPage:開發(fā)時(shí)使用的異常頁面,異常信息 UseStatusCodePages:返回狀態(tài)碼:400-

    2024年02月13日
    瀏覽(36)
  • 第一部分:核心容器

    第一部分:核心容器

    Spring就是一個(gè)輕量級(jí)的控制反轉(zhuǎn)(IOC)和面向切面編程(AOP)的框架! ????????什么是IoC、IoC容器、bean、DI ? IoC:對(duì)象創(chuàng)建控制權(quán)由程序轉(zhuǎn)移到IoC容器的控制反轉(zhuǎn)思想。 IoC容器:創(chuàng)建管理對(duì)象的容器。 bean:IoC容器中被創(chuàng)建管理的對(duì)象。 DI:IoC容器中建立bean之間依賴關(guān)

    2024年02月13日
    瀏覽(23)
  • 模擬第一部分5

    1、如果想要在外部包中使用全局變量,則全局變量必須( )?正確答案:A A、首字母必須大寫 B、首字母必須小寫 C、必須加上const D、必須加上var 答案解析:在函數(shù)體外聲明的變量稱之為全局變量。全局變量聲明必須以 var 開頭,如果想要在外部包中使用

    2024年02月08日
    瀏覽(33)
  • 6.播放音頻(第一部分)

    這一章將對(duì)播放音頻的具體內(nèi)容做講解。我的想法是按照tinyalsa中的例子作為講解的范本,因?yàn)閠inyalsa足夠簡單,很多時(shí)候都忽略了它的細(xì)節(jié)。趁著這個(gè)機(jī)會(huì)再整理一下tinyalsa的內(nèi)容。我使用的tinyalsa從https://github.com/tinyalsa/tinyalsa下載,從examples/writei.c開始。 其中函數(shù)read_file從

    2023年04月08日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包