国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

C語(yǔ)言指針的內(nèi)存分配和Java中的引用

2019-11-06 06:34:30
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

核心內(nèi)容: 1、C語(yǔ)言指針的核心知識(shí)點(diǎn) 2、處理指針相關(guān)問(wèn)題的萬(wàn)能措施—-內(nèi)存分配圖 3、C語(yǔ)言的指針是如何過(guò)渡到java中的引用的


最近一段時(shí)間一直在學(xué)習(xí)C語(yǔ)言的指針,也算是頗有心得吧,雖然從網(wǎng)上看了幾篇關(guān)于指針的博文,但是感覺(jué)都不符合自己的口味,于是決定好好寫一篇關(guān)于指針的文章。 C語(yǔ)言指針的核心知識(shí)點(diǎn): 1、指針就是地址,地址就是內(nèi)存單元的編號(hào),范圍是0到4G-1,指針的本質(zhì)就是一個(gè)操作受限的非負(fù)整數(shù),而指針變量就是存放內(nèi)存單元編號(hào)(即地址、指針)的變量。 2、凡是動(dòng)態(tài)分配的內(nèi)存,都是沒(méi)有名字的,而是將其地址賦給一個(gè)指針變量,用指針變量去代表這個(gè)事物。 3、一個(gè)指針變量,無(wú)論其指向的變量占多少個(gè)字節(jié),其本身只占用4個(gè)字節(jié)的內(nèi)存空間,因?yàn)閮?nèi)存單元的編號(hào)是32位。32/8=4 4、字節(jié)是存儲(chǔ)數(shù)據(jù)的基本單元,一個(gè)字節(jié)占8位,而一個(gè)字節(jié)的編號(hào)占32位。 5、變量分為兩種類型:普通類型變量和指針類型變量,其中普通類型變量用來(lái)存放真實(shí)的數(shù)據(jù),而指針類型變量用來(lái)存放變量的地址。其中指針類型變量包括(Java中): ①所有類定義的變量:如 Student student = new Student(“zhang” , 25),其中的student ②所有接口定義的變量:如 List list = new ArrayList(),其中的list ③數(shù)組的名字:如int a[] = {1,2,3,8,9}中的a。 6、靜態(tài)內(nèi)存是在棧中進(jìn)行分配的,是由系統(tǒng)自動(dòng)分配、自動(dòng)釋放的,靜態(tài)內(nèi)存是程序員無(wú)法控制的;動(dòng)態(tài)內(nèi)存是在堆中進(jìn)行分配的,是由程序員手動(dòng)分配,手動(dòng)釋放的,凡是動(dòng)態(tài)分配的內(nèi)存必須通過(guò)free的方式才能夠進(jìn)行釋放,當(dāng)然這里指的是C語(yǔ)言;在Java當(dāng)中,動(dòng)態(tài)分配的內(nèi)存是由內(nèi)存回收機(jī)制來(lái)回收的,不用程序員來(lái)進(jìn)行手動(dòng)回收,保證了程序的安全性,但是在Java當(dāng)中,由于虛擬機(jī)要一直跟蹤每一塊內(nèi)存空間的使用情況,所以往往會(huì)從造成CPU的使用率過(guò)大。 好的,如果你想學(xué)會(huì)C語(yǔ)言中的指針,上面的這些內(nèi)容是你必須要理解的,首先我們先理解一下究竟什么是指針,在理解究竟什么是指針之前,我們必須要知道數(shù)據(jù)在內(nèi)存中究竟是如何來(lái)進(jìn)行存儲(chǔ)的,先放一張圖: 這里寫圖片描述 這里通過(guò)一個(gè)小例子來(lái)說(shuō)明數(shù)據(jù)在內(nèi)存中是如何來(lái)進(jìn)行存儲(chǔ)的: 這里寫圖片描述 當(dāng)我們?cè)赩isiual C++6.0軟件對(duì)這個(gè)程序進(jìn)行編譯運(yùn)行的時(shí)候,Visiual C++6.0這個(gè)軟件首先請(qǐng)求操作系統(tǒng)為我們的變量i分配一塊內(nèi)存空間,隨后操作系統(tǒng)會(huì)在內(nèi)存中尋找一塊空閑的區(qū)域分配給我們的程序,隨后Visiual C++6.0這個(gè)軟件會(huì)將變量i和我們的這塊內(nèi)存空間關(guān)聯(lián)起來(lái),今后對(duì)變量i的操作就是對(duì)我們內(nèi)存空間的操作。具體實(shí)現(xiàn)過(guò)程如下: 這里寫圖片描述 現(xiàn)在我們對(duì)內(nèi)存存儲(chǔ)的這一塊區(qū)域進(jìn)行放大: 這里寫圖片描述 操作系統(tǒng)會(huì)給我們的變量分配一塊內(nèi)存空間,但是這塊內(nèi)存空間究竟在內(nèi)存中的什么位置呢?這塊內(nèi)存空間在內(nèi)存空間中的編號(hào)到底是多少呢?現(xiàn)在讓我么在程序中輸出一下:

# include <stdio.h>int main(){    int i = 10;    PRintf("編號(hào)1的數(shù)值是:%#X/n",&i);    return 0;}1234567891012345678910

運(yùn)行結(jié)果: 這里寫圖片描述 現(xiàn)在我們用圖畫在描述一下: 這里寫圖片描述 在上面這張圖中:這里寫圖片描述(即編號(hào)1)就是我們所說(shuō)的指針,即地址,也就是說(shuō):指針實(shí)際上就是內(nèi)存單元的編號(hào),一個(gè)編號(hào)為32位,每一個(gè)內(nèi)存單元都會(huì)占有一個(gè)內(nèi)部單元的編號(hào)(即地址)記載其在內(nèi)存條中的位置,因此通過(guò)指針我們可以直接對(duì)硬件進(jìn)行操作。 其實(shí),程序歸根結(jié)底就是對(duì)內(nèi)存的操作,我們對(duì)一塊內(nèi)存空間進(jìn)行操作總共含有兩種方式: ①直接通過(guò)變量名的方式對(duì)這塊內(nèi)存空間進(jìn)行操作。(直接訪問(wèn)) ②通過(guò)獲取內(nèi)存空間的地址對(duì)這塊內(nèi)存空間進(jìn)行操作。(間接訪問(wèn)) 這里寫圖片描述 其中,第一種方式是我們經(jīng)常使用的,但是第二種方式會(huì)讓我們有一種直接接觸到硬件的感覺(jué),示例程序:

# include <stdio.h>int main(){    int i = 10;    printf("編號(hào)1的數(shù)值是:%#X/n",&i);    int * p = &i; //指針變量p保存了變量i的地址:18FF44    *p = 100; //以18FF44為地址的那塊內(nèi)存空間的內(nèi)容設(shè)置為100    printf("變量i的內(nèi)容是:%d/n",i);//無(wú)論是直接訪問(wèn)還是以地址的間接訪問(wèn),本質(zhì)上都是對(duì)同一塊內(nèi)存空間的訪問(wèn)    return 0;}1234567891011121314151612345678910111213141516

運(yùn)行結(jié)果: 這里寫圖片描述 具體效果: 這里寫圖片描述 歸根接地就是一句話:無(wú)論是通過(guò)變量名i的直接訪問(wèn),還是通過(guò)地址18FF44的間接訪問(wèn),本質(zhì)上都是對(duì)同一塊內(nèi)存空間的訪問(wèn)。


處理指針相關(guān)問(wèn)題的萬(wàn)能措施—-內(nèi)存分配圖 很多人在處理指針這塊的程序的時(shí)候,有的時(shí)候總是會(huì)感覺(jué)到很迷糊,但是就我個(gè)人而言,對(duì)于指針相關(guān)的知識(shí),總是習(xí)慣于去畫內(nèi)存分配圖去解決問(wèn)題,而且效果還是非常好的,下面我們就用一個(gè)典型的程序:交換內(nèi)容的程序來(lái)說(shuō)明問(wèn)題。 要求:輸入a和b兩個(gè)整數(shù),按照先大后小的順序輸出a和b。 實(shí)例程序1:

# include <stdio.h>void swap(int ,int );int main(){    int a,b;    printf("請(qǐng)從鍵盤上輸入a和b兩個(gè)數(shù)值:/n");    scanf("%d %d",&a,&b);    if (a < b)    {       swap(a,b);       }    printf("max=%d /t min=%d /n",a,b);    return 0;}void swap(int p,int q){    int tmp; //交換p和q的內(nèi)容    tmp = p;    p = q;    q = tmp;}12345678910111213141516171819202122232425261234567891011121314151617181920212223242526

運(yùn)行結(jié)果: 這里寫圖片描述 很明顯,從運(yùn)行結(jié)果上來(lái)看,并沒(méi)有達(dá)到我們的預(yù)期效果,下面我們用內(nèi)存分配圖來(lái)查找一下原因: 這里寫圖片描述 所以上面程序的解法是錯(cuò)誤的。 實(shí)例程序2:

# include <stdio.h>void swap(int *,int *);int main(){    int a,b;    printf("請(qǐng)從鍵盤上輸入a和b兩個(gè)數(shù)值:/n");    scanf("%d %d",&a,&b);    if (a < b)    {       swap(&a,&b);     }    printf("max=%d /t min=%d /n",a,b);    return 0;}void swap(int *p,int *q){    int tmp;    tmp = *p;    *p = *q;    *q = tmp;}12345678910111213141516171819202122232425261234567891011121314151617181920212223242526

運(yùn)行結(jié)果: 這里寫圖片描述 內(nèi)存分配圖: 這里寫圖片描述 通過(guò)上面的圖解我們可以發(fā)現(xiàn),指針變量p和q分別定位到了變量a和變量b的內(nèi)存空間,間接的交換了a和b內(nèi)存空間的內(nèi)容。


C語(yǔ)言的指針是如何過(guò)渡到Java中的引用的 在談到這個(gè)問(wèn)題的時(shí)候,我認(rèn)為應(yīng)該從兩個(gè)方面進(jìn)行說(shuō)起:動(dòng)態(tài)內(nèi)存分配和如何傳遞發(fā)送內(nèi)容。 動(dòng)態(tài)內(nèi)存份分配的問(wèn)題: 實(shí)例程序1:

# include <stdio.h># include <malloc.h># include <string.h>struct Student{   char name[100];   int age;   float score;};int main(){    Student * student = (Student *)malloc(sizeof(Student));    strcpy(student->name,"zhangming");    student->age = 25;    student->score = 88.8f;    printf("name is %s/n",student->name); //student->age在編譯底層會(huì)變?yōu)?*student).name    printf("age is %d/n",student->age);    printf("score is %f/n",student->score);    return 0;}1234567891011121314151617181920212223242512345678910111213141516171819202122232425

運(yùn)行結(jié)果: 這里寫圖片描述 內(nèi)存實(shí)例圖示: 這里寫圖片描述 對(duì)于上面的這個(gè)程序,Java語(yǔ)言是這么封裝的:

class Student {   String name;   int age;   float score;}public class App1 {    public static void main(String[] args)    {        //Student * student = (Student *)malloc(sizeof(Student));        Student student = new Student(); //new相當(dāng)于C語(yǔ)言中的malloc        student.name = "zhangsan";        student.age = 25;        student.score = 88.8f;        System.out.println("name is:"+student.name);        System.out.println("age is:"+student.age);        System.out.println("score is:"+student.score);    }}123456789101112131415161718192021123456789101112131415161718192021

下面我們通過(guò)函數(shù)傳遞數(shù)據(jù):傳遞指針變量(本質(zhì)傳遞的是地址)

# include <stdio.h># include <malloc.h># include <string.h>struct Student{   char name[100];   int age;   float score;};void changeData(Student * stu){    strcpy(stu->name,"lisi");    stu->age = 24;    stu->score = 98.8f;}int main(){    Student * student = (Student *)malloc(sizeof(Student));    strcpy(student->name,"zhangming");    student->age = 25;    student->score = 88.8f;    printf("name is %s/n",student->name); //student->age在編譯底層會(huì)變?yōu)?*student).name    printf("age is %d/n",student->age);    printf("score is %f/n",student->score);    changeData(student);//傳遞的是地址,速度快并且節(jié)省內(nèi)存空間!    printf("name is %s/n",student->name); //student->age在編譯底層會(huì)變?yōu)?*student).name    printf("age is %d/n",student->age);    printf("score is %f/n",student->score);    return 0;}123456789101112131415161718192021222324252627282930313233343536123456789101112131415161718192021222324252627282930313233343536

運(yùn)行結(jié)果: 這里寫圖片描述 Java封裝的效果:

class Student {   String name;   int age;   float score;}public class App1 {    public static void main(String[] args)    {        //Student * student = (Student *)malloc(sizeof(Student));        Student student = new Student(); //new相當(dāng)于C語(yǔ)言中的malloc        student.name = "zhangsan";        student.age = 25;        student.score = 88.8f;        System.out.println("name is:"+student.name);        System.out.println("age is:"+student.age);        System.out.println("score is:"+student.score);        changeData(student); //student本質(zhì)上是一個(gè)指針變量        System.out.println("name is:"+student.name);        System.out.println("age is:"+student.age);        System.out.println("score is:"+student.score);    }    public static void changeData(Student stu) //stu指向同一塊內(nèi)存空間    {        stu.name = "lisi";        stu.age = 24;        stu.score = 98.8f;    }}123456789101112131415161718192021222324252627282930313233123456789101112131415161718192021222324252627282930313233

運(yùn)行結(jié)果:

name is:zhangsanage is:25score is:88.8name is:lisiage is:24score is:98.8123456123456

總結(jié):在Java當(dāng)中,雖然已經(jīng)沒(méi)有了指針,但是底層編譯運(yùn)行過(guò)程中本質(zhì)上就是指針,Java中的引用本質(zhì)上就是C語(yǔ)言中的指針變量,無(wú)論是C語(yǔ)言還是Java語(yǔ)言,都有一個(gè)共同的特點(diǎn):凡是動(dòng)態(tài)分配的內(nèi)存都是沒(méi)有名字的,而是用一個(gè)指針變量保存這塊內(nèi)存空間的地址,用這個(gè)指針變量去代表這塊內(nèi)存空間。 


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 张北县| 滕州市| 广州市| 蒙山县| 浠水县| 泸溪县| 乌恰县| 辽阳县| 徐州市| 栖霞市| 沛县| 长丰县| 左权县| 平度市| 石屏县| 泸定县| 清新县| 唐河县| 吉林省| 曲沃县| 同心县| 绥阳县| 柘荣县| 和田县| 吴江市| 沾化县| 会宁县| 梅州市| 拉萨市| 嘉义市| 朝阳区| 卓资县| 安新县| 长治市| 丰都县| 邵东县| 长子县| 托克逊县| 临高县| 洛扎县| 普安县|