c語言學(xué)習(xí)之路——由淺入深(快速掌握c基礎(chǔ))文章

今天小編給大家?guī)韈語言學(xué)習(xí)之路--由淺入深(快速掌握c基礎(chǔ))。溫馨提示:亮點在最后嫌褪!

1.第一個C程序:HelloWorld.c

首先我這里是使用這個軟件編寫的:下載地址:文章末尾

安裝過程一直next就好了

安裝后在你的代碼目錄創(chuàng)建一個HelloWorld.c喉童,代碼目錄可以隨意,然后雙擊打開HelloWorld.c就可以默認進入我們下載的c開發(fā)軟件中,如圖:

其中圖中標(biāo)記為我們java中常用的編譯和運行

下面就可以開始我們c語言的第一個helloWorld,通常說從helloWorld開始可以快速成為大神:

#include // java import xxx.xx.pack 引用函數(shù)的聲明 #include

main() // 程序的入口函數(shù)

{

//代碼文件目錄是本級目錄則會執(zhí)行成功露戒,否則會找不到該類

printf("Hello world ! "); // 控制臺打印一個hello world

//如果不是本級目錄必須先指定目錄地址描验,才能執(zhí)行成功

system("java -classpath c:\ HelloWorld");

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

代碼中我們首先可以看到

1白嘁、 這個東西拿java來說就是我們通常的包名

2、main函數(shù)是主入口膘流,和java一樣

3絮缅、c語言中必須使用system("pause");使命令行暫停,方便觀察程序的執(zhí)行結(jié)果呼股,否則結(jié)果會在你眼中一閃而過

2.C語言的基本類型與JAVA基本類型對比:

上一節(jié)中我們開始我們的第一個helloWorld耕魄,下面我們講學(xué)習(xí)c中的數(shù)據(jù)類型:

// java數(shù)據(jù)類型 和長度int 4個字節(jié) double 8個字節(jié) float 4個字節(jié) long 8個字節(jié)

// short 2個字節(jié) boolean 1個字節(jié) char 2個字節(jié) byte 1個字節(jié)

// char, int, float, double, signed, unsigned, long, short and void

// c語言中 數(shù)據(jù)類型比java少一些 在c語言中沒有 boolean類型的數(shù)據(jù) int 1 代表真 0 代表假

// c 語言中沒有String類型的數(shù)據(jù) java中表示一個字符串 String , c語言中表示字符串 通過char類型的數(shù)組來表示字符串

// c 語言沒有byte類型 所有用char的類型表示byte類型

#include #include

// sizeof(); c語言的一個函數(shù) 可以把 某種數(shù)據(jù)類型的長度獲取出來 int

main()

{ // %d 類似sql語句的? 占位符

printf("char的長度為%d ", sizeof(char));//1

printf("int的長度為%d ", sizeof(int));//4

printf("float的長度為%d ", sizeof(float));//4

printf("double的長度為%d ", sizeof(double));//8

printf("long的長度為%d ", sizeof(long));//在不同的情況下可能會有不同的大小,但是long的長度一定比int大 4

printf("short的長度為%d ", sizeof(short));// 2

//signed, unsigned, 數(shù)據(jù)類型的修飾符

// signed int ; 代表的是有符號的int的數(shù)據(jù)

// unsigned int ; 無符號的int數(shù)據(jù)

printf("signed int的長度為%d ", sizeof( signed int));//4

printf("unsigned int的長度為%d ", sizeof( unsigned int));//4

// 符號的修飾符 只能修飾 整數(shù)類型的數(shù)據(jù) long int

// 不能修飾 浮點型的數(shù)據(jù) float double

// printf("signed float的長度為%d ", sizeof( signed float));

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

從上面我們可以知道彭谁,c語言有以下幾種數(shù)據(jù)類型:

char, int, float, double, long, short

使用char表示java的byte類型數(shù)據(jù)

使用char數(shù)據(jù)去表示java中String類型的數(shù)據(jù)

c的兩種修飾符 signed, unsigned,

3.C語言中的輸入輸出函數(shù):

上一節(jié)我們了解c語言的基本數(shù)據(jù)類型吸奴,下面我們看看c的輸入輸出函數(shù):

/*%d - int

%ld – long int

%c - char

%f - float

%lf – double

%x – 十六進制輸出 int 或者long int 或者short int

%o - 八進制輸出

%s – 字符串

Int len;

Scanf("%d",&len);*/#include // java import xxx.xx.pack 引用函數(shù)的聲明 #include

main() // 程序的入口函數(shù)

{ int i = 3;

float f = 3.1415;

double d = 6.2815;

char c = 'A'; //通過單引號定義字符

short s = 2;

//輸出的時候占位符和數(shù)據(jù)類型必須一一對應(yīng),否則得不到正確的結(jié)果

printf("int i=%d ",i);

printf("float f=%f ",f);

printf("char c=%c ",c);

printf("double d=%lf ",d);

printf("short s=%d ",s);

/*char arr[20] ; //定義一個長度為20的數(shù)組

//java中是System.in

scanf("%s",arr); // 從鍵盤接受一個字符串,放在c數(shù)組里面

//java中是System.out

printf("s =%s ",arr);

*/

int j ;

scanf("%d", &j);//&代表的是取地址

//從控制臺得到j(luò)地址所代表的址輸出

printf("j=%d ",j);

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

從代碼中我們知道c語言的 輸入:scanf();函數(shù) 根據(jù)地址去輸入&j 輸出:printf();函數(shù)

4.指針入門:

上一節(jié)我們學(xué)到了輸入輸出,下面我們將學(xué)習(xí)一個新名詞指針 首先java中是沒有指針這個名詞的奄抽,

指針是什么? 指針就是一個地址 地址代表的就是一塊內(nèi)存空間 指針變量是什么蔼两? 用來存放指針

從上面我們就可以知道java中的內(nèi)存控件就是c語言中的指針,下面我們看下代碼:

#include #include

main()

{

int i =5;// 定義一個int 類型的變量i 值 =5

//%#X表示16進制的地址占位符

printf("i的地址 %#X ",&i);

//獲取i的地址逞度,&i就是一個指針

// &i;

//定義一個指針變量额划,數(shù)據(jù)類型*

int* p ; // 指針變量 定義一個int* 類型的變量p

//其他兩種表示方式:int *p, int * p;

p = &i; // 就是把i的指針賦給指針變量p ,現(xiàn)在指針變量p里面存放的內(nèi)容(數(shù)據(jù)) 就是i的地址

printf("p里面的內(nèi)容為(i的地址) %#X ",p);

//*號 操作符

// *號的幾種含義

//1 . *號放在某種數(shù)據(jù)類型的后面,代表就是這種數(shù)據(jù)類型的指針 int* float*

//2 . *號 代表一個乘法符號 3*5 = 15;

//3 . *號放在一個指針變量的前面 -> 代表取這個指針變量所存放的地址里面對應(yīng)的數(shù)據(jù)

printf("i=%d ",i);

printf("*p的值%d ",*p);

// 改變p的值 會不會影響i的值?

//p = NULL;

// printf("i=%d ",i);//5

// 改變i的值 會不會影響p的值?

// i = 100;

// printf("p里面的內(nèi)容為(i的地址) %#X ",p);

// 通過上述實驗 p和 i 是兩個不同的變量 ,改變i的值 不會影響 p的值,同理,更改p的值 也不會影響i的值

// 更改*p的值 會不會影響i的值

// *p = 88;

// printf("i=%d ",i); //88

// 更改i的值 會不會影響 *p的值呢?

// i = 99;

// printf("*p的值%d ",*p); //99

//*p 和i 其實代表的是同一個變量,代表是同一塊內(nèi)存空間

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

從代碼中我們可以知道:

· 1.指針就是地址,而c語言中我們在變量前面加上&符號就可以到地址也就是指針如:int i=9;那么i的指針表示方式是&i

· 2.指針變量就是用來存放指針的一個變量档泽,如:數(shù)據(jù)類型* 變量名俊戳;如:int * p 這樣就是一個指針變量,將我們上面的&i=p這樣我們就將i的指針放在了指針變量p中

· 3.得到指針變量中的值使用符號*,例如我們將上面指針變量p的指針i的值取出來表示就是:*p

· 4.*p 和i 其實代表的是同一個變量,代表是同一塊內(nèi)存空間

·

5.指針介紹:

上一節(jié)我們已經(jīng)知道了指針和指針變量的用法,下面我們將通過一個小程序進一步說明指針

#include #include

main()

{

// 所有的變量都會分配一塊內(nèi)存空間

// 指針就是用來表示一塊內(nèi)存空間的地址的

// 地址可以用過 &這個符號獲取到某個變量的在內(nèi)存中的地址

// 這個地址如果想把他存放起來 就需要有一個變量 去存放這個地址

// 存放內(nèi)存地址的變量 就是指針變量

// 指針和指針變量

// 指針是用來表示一塊內(nèi)存地址的,

// 指針變量是用來存放一個內(nèi)存地址的 .

//

printf("ready go! 剩余時間60秒 ");

int time = 60;

printf("time變量對應(yīng)的內(nèi)存地址為%#X ", &time);

for(;time>0;time--){

printf("剩余時間%d ",time);

sleep(4000);

}

printf("游戲結(jié)束");

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

從代碼中我們編寫了一個for循環(huán)馆匿,打印time指針值抑胎,可以在命令行程序已經(jīng)在開始走了

從圖中可能大概你們可以看到我使用一個外掛軟件找到了time指針值,外掛地址

怎么使用外掛軟件:

1.首先點擊圖中的箭頭圖標(biāo)渐北,

2. 彈出Process List在里面找到我們的程序阿逃,然后點擊,

3.左邊Address欄就會出現(xiàn)我們程序中的time地址

從圖中我們居然看到我們的程序運行到22的時候怎么又從59開始了赃蛛,正常情況下我們是21啊恃锉,這是怎么回事呢??哈哈,這其實就是用到了我們上圖 中的外掛呕臂,首先我們使用外掛找到我們的time地址破托,然后將time 的值改為60之后就發(fā)現(xiàn)命令行又從60開始了。

通過這個外掛我們就更加深刻了解指針的作用歧蒋,下面我們將使用幾個案例去了解指針的一些細節(jié)

6.案例:使用指針交換兩個數(shù)據(jù):

#include

#include

// 問 java 中有值傳遞和引用傳遞 嗎? 他們的區(qū)別是什么?

// 其實在java中只有值傳遞 , 沒有引用傳遞

// Person p = new Person(); p里面存放的內(nèi)容 就是person對象的地址

void swap2(int* p , int* q){ // 傳遞的形參為 i 和j 變量的地址

// *p 代表 i *q 代表就是 j

int temp;

temp = *p;

*p = *q;

*q = temp;

}

void swap1(int i ,int j){ // 形參 i 和j 跟主函數(shù)里面的i和j是兩個不同的變量

printf("子函數(shù) i 地址%#X ",&i);

printf("子函數(shù) j 地址%#X ",&j);

int temp;

temp = i;

i = j;

j = temp;

}

main()

{

//利用指針 可以在子函數(shù)里面修改主函數(shù)里面的數(shù)據(jù)

int i = 3;

int j = 5;

printf("i=%d ",i);

printf("j=%d ",j);

printf("主函數(shù) i 地址%#X ",&i);

printf("主函數(shù) j 地址%#X ",&j);

/*/交換兩個數(shù)字

int temp;

temp = i;

i = j;

j = temp;

*/

//方法一中確實將i,j的值交換了土砂,但是當(dāng)函數(shù)一執(zhí)行完,函數(shù)被回收谜洽,i,j就被銷毀了萝映,交換失敗

// swap1(i,j);

//方法二接收的是i,j的地址,i褥琐,j在main函數(shù)里锌俱,所以數(shù)據(jù)交換成功

swap2(&i,&j);

printf("交換后 ");

printf("i=%d ",i);

printf("j=%d ",j);

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

7.案例:使用指針獲取子函數(shù)的數(shù)據(jù):

#include

#include

//int** q 表示里面存放的是一個int* q的指針

f(int** q){

int i = 3;

printf("子函數(shù) i的地址 %#X ",&i);

// *q 代表的就是p變量

*q = &i;

} /**

使用指針的時候 不可以訪問已經(jīng)被系統(tǒng)回收掉的數(shù)據(jù)

子函數(shù)執(zhí)行完畢后 子函數(shù)里面所有的局部變量都會別系統(tǒng)回收

*/

main()

{

// 希望在主函數(shù)里面去使用子函數(shù)里面的變量 i

// f();

// 希望在主函數(shù)里面得到子函數(shù) 里面int i變量的地址

int* p ; //存放子函數(shù)f中 int i的地址的一個變量

f(&p);

/**在6中我們已經(jīng)說過函數(shù)會被回收晤郑,

* 當(dāng)f()函數(shù)一執(zhí)行完敌呈,就會被回收,i就會被回收

* 但是回收是有一定的時間造寝,所以如果我們在正在回收還未回收完全時去取值磕洪,

* 會得到正確的值或者地址,但是如果我們比如下面我先打印地址值诫龙,在去打印*p

* 此時p是i的地址值析显,而*p就不是了,因為此時i被回收了,但是我們注釋輸入地址值

* 此時*p就會成功打印i的值

*/

// printf("主函數(shù) i的地址 %#X ",p);

// printf("i的值為 %d ",*p);

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

8.案例:使用指針返回一個以上的值

#include

#include

// public List getPersons() {};

// public byte[] getbytes(){};

/*

如果讓子函數(shù) 更改主函數(shù)里面的數(shù)據(jù)

如何讓子函數(shù) 返回一個以上的值

1.子函數(shù)的形參 為 主函數(shù)中要修改的變量的地址

2. 調(diào)用子函數(shù)的時候 把要修改的變量的地址 傳遞給子函數(shù)

3. 在子函數(shù)里面 修改這個地址里面存放的變量的內(nèi)容

4. 主函數(shù)使用這個變量的時候 里面的值就發(fā)生了變化

*/

int f(int* p, int* q){

*p = 33;

*q = 55;

}

main()

{

int i = 3;

int j = 5;

f(&i,&j);

printf("i=%d ",i);//33

printf("j=%d ",j);//55

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

6.7.8案例總結(jié):

1.子函數(shù)在main函數(shù)中調(diào)用結(jié)束后會被銷毀签赃,隨之傳入的形參也會被銷毀

2.main函數(shù)里的數(shù)據(jù)要想通過子函數(shù)進行交互谷异,子函數(shù)的傳入的參數(shù)必定是指針變量

3.方法中的返回值不能像java中一樣返回集合之類的數(shù)據(jù)分尸,通過指針去返回多個數(shù)據(jù)。

9.指針的常見錯誤:

通過6歹嘹、7箩绍、8節(jié)我們細致的了解了指針,下面我們將講解指針的一些錯誤:

#include #include

main()

{

/* int* p; //定義一個指針變量 垃圾值 -> 野指針

//printf("*p=%d ",*p);

*p = 1231;

// 立刻藍屏

//

指針變量如果沒有賦值就不能使用

*/

/* int d = 324233;

char* c; ; // 編譯錯誤 不符合的指針類型

c = &d;

printf("*p = %c ",*c);

類型不相同的指針不可以互相轉(zhuǎn)換

*/

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

錯誤總結(jié):

1.指針變量中必須得有指針尺上,否則在取指針變量中的指針的值的時候會異常

2.不能給沒有定義指針的指針變量的指針的值賦值

3.指針變量和指針的數(shù)據(jù)類型必須一一對應(yīng)

10材蛛、指針占多少個字節(jié):

之前第二2節(jié)中我們知道了c的基本數(shù)據(jù)類型的字節(jié)數(shù),那么指針占多少個字節(jié)呢怎抛? 看代碼:

#include #include

main()

{

int i =3;

double d = 3.141692;

float f = 3.1423;

char c ='B';

int* ip = &i;

double* dp = &d;

float* fp = &f;

char* cp = &c;

//電腦不同輸入的值可能是4可能是8

printf("int 類型指針變量的長度為 %d ",sizeof(ip)); //8

printf("double 類型指針變量的長度為 %d ",sizeof(dp)); //8

printf("float 類型指針變量的長度為 %d ",sizeof(fp)); //8

printf("char 類型指針變量的長度為 %d ",sizeof(cp)); //8

// 在32位的操作系統(tǒng)上 因為程序 最大能使用的內(nèi)存空間的地址 就是2的32次方

// 指針只需要4位 就可以表示出來所有的內(nèi)存空間

// 64 并且編譯支持64位 8位

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

首先我們定義了不同的幾個變量卑吭,然后將他們的地址放入指針變量中,最后輸出马绝,我們居然發(fā)現(xiàn)輸出結(jié)果都一樣豆赏。

總結(jié):

1..指針變量的內(nèi)存大小是固定的,與數(shù)據(jù)類型沒有關(guān)系

2.指針變量的內(nèi)存大小最終取決于我們的電腦

11富稻、使用char* 指針表示字符串

在第二節(jié)中我們知道河绽,c語言中是使用char數(shù)組去表示一個java中的String字符串, 在我們學(xué)習(xí)指針之后我們將看看怎么用指針更加簡單的表示一個字符串:

#include #include

main()

{

char arr[20] ={'h','e','l','l','o',''};

// 利用char類型指針 方便的表示一個字符串

char* arr1= "hello world";

printf("%s",arr1);

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

從代碼中我們可以看到使用char數(shù)組的方式是比較復(fù)雜的唉窃,然后我們使用指針的方式:char* arr1="",這樣就可以簡單的直接表示一個字符串

注意:在java中我們定義數(shù)組可以int arr[]; int [] arr;但是在c語言中[]只能卸載變量名后面耙饰,如:int arr[]

12、指針與數(shù)組

指針進階:

#include

#include

// 數(shù)組是一塊連續(xù)的內(nèi)存空間 數(shù)組名 就是內(nèi)存空間的首地址

// 數(shù)組名[i] == *(數(shù)組名+i);

main()

{

/* char[] arr = new char[20];

char arr[] ;

*/

// 創(chuàng)建一個長度為5的int類型的數(shù)組

int arr[5] ={1,2,3,4,5};

printf("a[0]=%d ",arr[0]);

printf("a[4]=%d ",arr[4]);

// 邏輯上是錯誤的代碼 數(shù)組下標(biāo)越界

// printf("a[5]=%d ",arr[5]);

// windows xp 緩沖區(qū)越界補丁

// arr是一個什么東西呢?

printf("arr = %#X ",arr);

// 打印 數(shù)組的第一個元素的地址

printf("arr[0]地址 = %#X ",&arr[0]);

// 打印數(shù)組中的第二個元素

printf("arr[1]=%d ",arr[1]);

printf("arr[1]=%d ", *(arr+1));

//問題: arr[i] *(arr+i) 代表的是同一個變量么?

// 代表的是同一塊內(nèi)存空間 指向的是同一個變量

//通過實驗 : 數(shù)組名表示的 就是這個數(shù)組第一個元素 的首地址

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

· 語言語法上沒有數(shù)組越界纹份,在邏輯上存在數(shù)組越界苟跪,

· arr是一個指針,arr的指針就是&arr[0]的指針蔓涧,也就是說數(shù)組的指針就是數(shù)組第一個元素的指針

· 數(shù)組中的數(shù)據(jù)的指針是一塊連續(xù)的內(nèi)存空間

· arr[i]等同于*(arr+i)

13件已、指針的計算

通過上一節(jié)我們大概知道了指針與數(shù)組的關(guān)系,下面我們通過一個案例去鞏固一下:

#include #include

main()

{

int i =3; //天津的某個路上 蓋了一個房子 3

int j =5; // 北京的某個路上 蓋了一個房子 5

int* p = &i; // p 天津的門牌號

int* q = &j; // q 北京的門牌號

// 指針的運算和數(shù)組都是緊密關(guān)聯(lián)的

char arr[5]={'a','b','c','d','e'}; //一塊連續(xù)的內(nèi)存空間

char* p1 = &arr[2];

printf("char = %c ", *(p1-1));

// char 內(nèi)存中占用 1個字節(jié)

// int 內(nèi)存 中占用 4個字節(jié)

int intarr[5]={1,2,3,4,5}; //一塊連續(xù)的內(nèi)存空間

int* q1 = &intarr[2];

printf("char = %d ", *(q1-1));

// 指針的運算 按照 約定好的數(shù)據(jù)類型 偏移相對應(yīng)的內(nèi)存空間的大小

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

總結(jié):

1. 數(shù)組中的數(shù)據(jù)的指針是一塊連續(xù)的內(nèi)存空間

2. 指針的運算按照約定好的數(shù)據(jù)類型偏移相對應(yīng)的內(nèi)存空間的大小

14.案例:通過子函數(shù)打印數(shù)組

#include

#include #define pi 3.1415

// 寫一個子函數(shù) 打印數(shù)組里面的每一個元素

void printArr(int* arr, int len){ // arr是數(shù)組的首地址 len數(shù)組的長度

int i=0;

for(;i

// printf("arr[%d]=%d ",i,arr[i]); // arr[i] 和 *(arr+i) 代表的含義相同

printf("arr[%d]=%d ",i, *(arr+i));

}

}

main()

{

// int arr[10]={1,2,3,4,5};

printArr(&arr[0],10);

//1 .定義一個數(shù)組 缺陷 數(shù)組的長度 必須事先申請好

//2. 循環(huán)賦值

//3. 打印數(shù)組里面的內(nèi)容

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

總結(jié):

1.int arr[5]; 這一句代碼一旦執(zhí)行 ,就立刻會在內(nèi)存里面申請 5個內(nèi)存空間 每個內(nèi)存空間的大小可以存放一個int類型的數(shù)據(jù)

2.留下疑問:沒有辦法動態(tài)的增加這一塊空間的大小, 也沒辦法減小這一塊內(nèi)存空間元暴,只能提前寫死篷扩,例如我們代碼中arr[10],直接就將我們的arr數(shù)組大小寫死了

15茉盏、realloc()方法介紹

在上一節(jié)中我們留下的疑問是不能更改數(shù)組的內(nèi)存控件鉴未,而realloc()方法則完美解決了這個問題,具體使用方式:

int arr[10];

arr = realloc(arr,sizeof(int)*12); //空間的長度為12了

首先我們可以看到realloc接收兩個參數(shù):

1.第一個參數(shù)表示你需要更改大小的變量

2.第二個表示更改之后的長度

我們了解了realloc()方法是可以更改變量內(nèi)存大小的鸠姨,那么就會存在這樣一個問題铜秆,改變之后的內(nèi)存會不會覆蓋之前的數(shù)據(jù)呢?

1.對于增加內(nèi)存:realloc是直接在原有的基礎(chǔ)上添加內(nèi)存空間讶迁,所以還是會保持原有的數(shù)據(jù)再進行添加

2.對于減少內(nèi)存:realloc是會將排列在最后的內(nèi)存空間值給回收掉的连茧, 比如原始數(shù)據(jù)int arr[4]={1,2,3啸驯,4}客扎;減少2個內(nèi)存的話,就是int arr[8]={1,2}

·

16罚斗、動態(tài)分配內(nèi)存

前面我們看到我們定義的那些函數(shù)變量等虐唠,都是由系統(tǒng)給我們自動分配內(nèi)存,我們是不用去理會系統(tǒng)到底什么時候去給我們分配惰聂,什么時候去回收疆偿,

而接下我們要學(xué)習(xí)的是自己去管理內(nèi)存即動態(tài)分配內(nèi)存,看代碼:

#include

#include

#include

// malloc memory allocate 內(nèi)存申請

main()

{

// 接受一個參數(shù) 申請多大(byte)的內(nèi)存空間

int* p = (int*)malloc(sizeof(int)); // 在堆內(nèi)存里面申請一塊可以存放一個int類型數(shù)據(jù)的內(nèi)存空間

*p = 4; // 就是往 p 里面存放的地址 表示的那塊內(nèi)存空間里面存放一個int類型的數(shù)據(jù) 4

printf("*p=%d ",*p);

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

代碼中我們首先如java導(dǎo)入類的方式搓幌,在代碼上面添加了一行: 這個就是動態(tài)內(nèi)存所要用到的方法了杆故,接下來我們在main函數(shù)中 int* p = (int*)malloc(sizeof(int)); 這樣我們即給指針變量p分配了int字節(jié)大小的內(nèi)存空間,完成了一個動態(tài)分配內(nèi)存的操作

這樣我們就可以使用如上方式去解決上一節(jié)中的疑問了

學(xué)到的知識點:

· malloc(byte length)方法用于動態(tài)申請內(nèi)存溉愁。

· 動態(tài)申請內(nèi)存其實就是在申請指針

疑問:

· 我們之前看到的处铛,函數(shù)使用完成后是會被回收掉的,難道我們動態(tài)申請內(nèi)存怎么被回收呢拐揭?不然是會浪費內(nèi)存空間的

17撤蟆、動態(tài)分配內(nèi)存2

在上節(jié)中我們已經(jīng)知道了malloc(byte length)方法是用來動態(tài)分配內(nèi)存的, 下面我們將通過一個小案例來進一步講解動態(tài)分配內(nèi)存堂污,并且解決上一節(jié)中的疑問

#include

#include

#include

f(int** address){ //address 存放的是q的地址

// 動態(tài)的在堆內(nèi)存里面申請一塊空間

int* p ;

p = (int*)malloc(sizeof(int)*3);

*p = 3;

*(p+1) = 4;

*(p+2) = 5 ;

printf("子函數(shù)里面 地址%#X ",p);

*address = p;

// 在子函數(shù)里面把p釋放掉了

//free(p);

}

main()

{

int* q ;

f(&q);

printf("主函數(shù)里面 地址%#X ",q);

printf("*q = %d ",*(q+0));

printf("*q = %d ",*(q+1)); // 殘留的內(nèi)存映像

printf("*q = %d ",*(q+2));

//動態(tài)內(nèi)存分配 程序員可以自己手工的決定一個變量的生命周期

//手工的釋放調(diào)用內(nèi)存空間

//不要使用已經(jīng)回收掉的內(nèi)存空間里面的數(shù)據(jù)

system("pause"); // 調(diào)用windows下系統(tǒng)的命令 讓程序暫停執(zhí)行 方便觀察程序的執(zhí)行結(jié)果

}

首先我們看到是f(int** address) 其中int **表示的是多級指針家肯,下面我們會詳細介紹,在這里只要知道他是一個存放指針變量的指針變量就行了盟猖, 然后定義一個指針變量p并動態(tài)分配內(nèi)存和賦值讨衣, 最后將p傳遞給f(int** address)的形參

接著我們看到main函數(shù)中我們使用了f()函數(shù)并得到了f()函數(shù)中的值

細心的同學(xué)可能可以看到我們在f()方法中可以看到我們注釋的一個函數(shù):free(p)

free(p):將動態(tài)釋放的內(nèi)存給回收,使用free(p)函數(shù)即可解決我們在上一節(jié)留下的疑問,其中p是我們需要釋放內(nèi)存的指針變量

接著我將free(p)打開式镐,按理說p分配的動態(tài)內(nèi)存空間的數(shù)據(jù)是會被free(p)執(zhí)行后給回收的反镇,最后居然發(fā)現(xiàn)在main函數(shù)打印(q+0)為0,(q+1)為4娘汞,(q+2)為5歹茶, 結(jié)果可想而知free(p)難道只將第一個數(shù)據(jù)給回收了?其實在執(zhí)行free(p)之后確實將p給回收了你弦,(q+1)為4惊豺,(q+2)為5,只是殘留的映像鳖目,在回收過程中只是將p的內(nèi)存空間標(biāo)記為可以再次寫入扮叨,其實真正并沒有徹底回收,所以會出現(xiàn)這種情況

寫在最后

關(guān)于怎么快速學(xué)C/C++,可以加下小編的C/C++學(xué)習(xí)群:领迈,814+974+917,邀請碼:云志,不管你是小白還是大牛狸捅,小編我都歡迎衷蜓,不定期分享干貨,歡迎初學(xué)和進階中的小伙伴尘喝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末磁浇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子朽褪,更是在濱河造成了極大的恐慌置吓,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缔赠,死亡現(xiàn)場離奇詭異衍锚,居然都是意外死亡,警方通過查閱死者的電腦和手機嗤堰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門戴质,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人踢匣,你說我怎么就攤上這事告匠。” “怎么了离唬?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵后专,是天一觀的道長。 經(jīng)常有香客問我输莺,道長行贪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任模闲,我火速辦了婚禮建瘫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尸折。我一直安慰自己啰脚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布实夹。 她就那樣靜靜地躺著橄浓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亮航。 梳的紋絲不亂的頭發(fā)上荸实,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音缴淋,去河邊找鬼准给。 笑死泄朴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的露氮。 我是一名探鬼主播祖灰,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畔规!你這毒婦竟也來了局扶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤叁扫,失蹤者是張志新(化名)和其女友劉穎三妈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莫绣,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡畴蒲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了兔综。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饿凛。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖软驰,靈堂內(nèi)的尸體忽然破棺而出涧窒,到底是詐尸還是另有隱情,我是刑警寧澤锭亏,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布纠吴,位于F島的核電站,受9級特大地震影響慧瘤,放射性物質(zhì)發(fā)生泄漏遍搞。R本人自食惡果不足惜艇拍,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一点楼、第九天 我趴在偏房一處隱蔽的房頂上張望甚亭。 院中可真熱鬧,春花似錦怔匣、人聲如沸握联。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽金闽。三九已至,卻和暖如春剿骨,著一層夾襖步出監(jiān)牢的瞬間代芜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工浓利, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挤庇,地道東北人钞速。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像罚随,于是被迫代替她去往敵國和親玉工。 傳聞我的和親對象是個殘疾皇子羽资,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容