新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > C語言程序內(nèi)存分配

C語言程序內(nèi)存分配

作者: 時間:2016-11-27 來源:網(wǎng)絡(luò) 收藏

(1) & 與 * 操作

取地址運(yùn)算符 &: p = &c;

--表達(dá)式解析: 將 c 的地址賦值給 變量 p, p 是指向 c 變量的指針;

--& 可以使用的情況: 取地址操作 只能用于內(nèi)存中的對象, 如變量 或 數(shù)組, 棧內(nèi)存 堆內(nèi)存 都可以;

--& 不適用的情況: 不能用于 表達(dá)式, 常量, register類型變量;

間接引用運(yùn)算符: * ;

--聲明指針: int *p ; 該表達(dá)式的含義是*p 的結(jié)果是 int 類型, 聲明變量 a, int a, 聲明指針 *p , int *p;

--獲取指針指向的值: int a = *p ;

(2) 指針定義解析

聲明指針 和 函數(shù): int *p, max(int a, int b), 聲明指針變量 語法 與聲明 變量語法類似, 同理聲明函數(shù)也一樣;

--原理: *p 和 max()返回值 類型都是 int 類型;

指針指向: 每個指針都必須指向某種特定類型;

--例外: void *p 可以指向任何類型, 但是 p 不能進(jìn)行取值運(yùn)算, *p 是錯誤的, 因為不知道 p 指向的數(shù)據(jù)類型;

(3) 指針運(yùn)算及示例

指針相關(guān)運(yùn)算: int x = 0; int *p = &x; 那么*p 就可以代表x;

--算數(shù)運(yùn)算: x = x + 1; 等價于 *p = *p + 1 ; int y = x + 1; 等價于 int y = *p + 1;

--自增運(yùn)算: 前提 : ++, * 運(yùn)算順序是自右向左; ++*p 和 (*p)++, p 指向的值自增1, 注意要加上括號, 否則會將地址自增;

--指針賦值: int *p, *q; int a = 0; p = &a; q = p; 最終結(jié)果 p 和 q 都指向了 變量 a;

示例程序:

[cpp]view plaincopy
  1. /*************************************************************************
  2. >FileName:pointer_address.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Mon10Mar201409:52:01PMCST
  6. ************************************************************************/
  7. #include
  8. intmain(intargc,char**argv)
  9. {
  10. int*p,*q;
  11. inta=10,b;
  12. //p指針指向a變量
  13. p=&a;
  14. //*p可以代替a進(jìn)行運(yùn)算
  15. ++*p;
  16. b=*p+5;
  17. //指針之間可以直接相互賦值
  18. q=p;
  19. //打印p和q指針指向的值
  20. printf("*p=%d",*p);
  21. printf("*q=%d",*q);
  22. return0;
  23. }


執(zhí)行結(jié)果:

[cpp]view plaincopy
  1. [root@ip28pointer]#gccpointer_address.c
  2. [root@ip28pointer]#./a.out
  3. *p=11
  4. *q=11

4. 函數(shù)參數(shù)的傳值調(diào)用和傳址調(diào)用

(1) 傳值調(diào)用 和 傳址調(diào)用

傳值調(diào)用: 以傳值的方式將參數(shù)傳遞給函數(shù), 不能直接修改主函數(shù)中變量的值, 僅僅是將副本傳遞給了函數(shù);

傳址調(diào)用: 將 變量的指針 傳遞給函數(shù), 當(dāng)函數(shù)對指針進(jìn)行操作的時候, 主函數(shù)中的值也進(jìn)行了對應(yīng)變化;

交換函數(shù)示例1:

[cpp]view plaincopy
  1. /*************************************************************************
  2. >FileName:swap.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Mon10Mar201411:07:18PMCST
  6. ************************************************************************/
  7. #include
  8. voidswap_1(inta,intb)
  9. {
  10. inttemp;
  11. temp=a;
  12. a=b;
  13. b=temp;
  14. printf("swap_1傳值函數(shù)a=%d,b=%d",a,b);
  15. }
  16. voidswap_2(int*a,int*b)
  17. {
  18. inttemp;
  19. temp=*a;
  20. *a=*b;
  21. *b=temp;
  22. printf("swap_2傳址函數(shù)a=%d,b=%d",*a,*b);
  23. }
  24. intmain(intargc,char**argv)
  25. {
  26. inta=10,b=5;
  27. printf("初始值:a=%d,b=%d",a,b);
  28. swap_1(a,b);
  29. printf("執(zhí)行swap_1函數(shù),a=%d,b=%d",a,b);
  30. swap_2(&a,&b);
  31. printf("執(zhí)行swap_2函數(shù),a=%d,b=%d",a,b);
  32. return0;
  33. }


執(zhí)行結(jié)果:

[cpp]view plaincopy
  1. [root@ip28pointer]#gccswap.c
  2. [root@ip28pointer]#./a.out
  3. 初始值:a=10,b=5
  4. swap_1傳值函數(shù)a=5,b=10
  5. 執(zhí)行swap_1函數(shù),a=10,b=5
  6. swap_2傳址函數(shù)a=5,b=10
  7. 執(zhí)行swap_2函數(shù),a=5,b=10



示例解析:

--傳值調(diào)用: swap_1 是傳值調(diào)用, 傳入的是 main 函數(shù)中的 a b 兩個變量的副本, 因此函數(shù)執(zhí)行完畢后, 主函數(shù)中的值是不變的;

--傳址調(diào)用: swap_2 是傳址調(diào)用, 傳入的是 a , b 兩個變量的地址 &a, &b, 當(dāng)在swap_2 中進(jìn)行修改的時候, 主函數(shù)中的 a,b變量也會發(fā)生改變;

(2) 高級示例

需求分析: 調(diào)用getint()函數(shù), 將輸入的數(shù)字字符 轉(zhuǎn)為一個整形數(shù)據(jù);

getch 和 ungetch 函數(shù):

--使用場景: 當(dāng)進(jìn)行輸入的時候, 不能確定是否已經(jīng)輸入足夠的字符, 需要讀取下一個字符, 進(jìn)行判斷, 如果多讀取了一個字符, 就需要將這個字符退回去;

--使用效果: getch() 和 ungetch() 分別是預(yù)讀下一個字符, 和 將預(yù)讀的字符退回去, 這樣對于其它代碼而言, 沒有任何影響;

注意的問題 : 出現(xiàn)問題, 暫時編譯不通過, 找個C語言大神解決;

代碼:

[cpp]view plaincopy
  1. /*************************************************************************
  2. >FileName:getint.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Mon10Mar201411:40:19PMCST
  6. ************************************************************************/
  7. #include
  8. #include
  9. #include
  10. #defineSIZE5
  11. intgetint(int*p)
  12. {
  13. //sign是用來控制數(shù)字的正負(fù)
  14. intc,sign;
  15. //跳過空白字符,如果是空白字符,就會進(jìn)行下一次循環(huán),直到不是空白字符為止
  16. while(isspace(c=getc(stdin)));
  17. //如果輸入的字符不是數(shù)字,就將預(yù)讀的數(shù)據(jù)退回到標(biāo)準(zhǔn)輸入流中
  18. if(!isdigit(c)&&c!=EOF&&c!=+&&c!=-)
  19. {
  20. ungetc(c,stdin);
  21. return0;
  22. }
  23. /*
  24. *如果預(yù)讀的是減號,那么sign標(biāo)識就是-1,
  25. *如果預(yù)讀的是加號,那么sign標(biāo)識就是1;
  26. */
  27. sign=(c==-)?-1:1;
  28. //如果c是加號或者減號,再預(yù)讀一個字符&
  29. if(c==+||c==-)
  30. c=getc(stdin);
  31. for(*p=0;isdigit(c);c=getc(stdin))
  32. *p=10**p+(c-0);
  33. *p*=sign;
  34. if(c!=EOF)
  35. ungetc(c,stdin);
  36. returnc;
  37. }
  38. intmain(intargc,char**argv)
  39. {
  40. intn,array[SIZE],i;
  41. for(n=0;n
  42. for(i=0;i
  43. {
  44. printf("array[%d]=%d",i,array[i]);
  45. }
  46. return0;
  47. }

執(zhí)行結(jié)果:

[plain]view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/pointer$./a.out
  2. 123
  3. 12343
  4. 6741
  5. array[0]=123
  6. array[1]=123
  7. array[2]=43
  8. array[3]=674
  9. array[4]=1

5. 指針 和 數(shù)組

指針數(shù)組比較:

--可互相替代: 數(shù)組下標(biāo)執(zhí)行的操作都可以使用指針替代;

--效率比較: 使用指針操作效率比數(shù)組要高;

指針 與 數(shù)組初始化:

--聲明數(shù)組: int a[10]; 定義一個長度為10 的int數(shù)組;

--聲明指針: int *p; 定義一個指針, 該指針指向整型;

--相互賦值: p = &a[0], 將數(shù)組第一個元素的地址賦值給指針變量;

--使用指針獲取數(shù)組對象: *p 等價于 a[0], *(p + 1) 等價于 a[1], *(p + i)等價于 a[i];

--注意地址的運(yùn)算: p + i , 在地址運(yùn)算上, 每次增加 sizeof(int) * i 個字節(jié);

將數(shù)組賦值給指針的途徑:

--將數(shù)組第一個元素地址賦值給指針變量: p = &a[0];

--將數(shù)組地址賦值給指針變量: p = a;

指針 和 數(shù)組 訪問方式互換: 前提 int *p, a[10]; p = a;

--數(shù)組計算方式: 計算a[i]的時候, 先將數(shù)組轉(zhuǎn)化為 *(a + i)指針, 然后計算該指針值;

--取值等價: a[i] 等價于 *(p + i);

--地址等價: &a[i] 與 a + i 是等價的;

--指針下標(biāo)訪問: p[i] 等價于 *(p + i);

--結(jié)論: 通過數(shù)組和下標(biāo)實現(xiàn)的操作 都可以使用指針和偏移量進(jìn)行等價替換;

指針 和 數(shù)組 的不同點:

--指針是變量: int *p, a[10]; p = a 和 p++ 沒有錯誤;

--數(shù)組名不是變量: int *p, a[10]; a = p 和 a++ 會報錯;

數(shù)組參數(shù):

--形參指針: 將數(shù)組傳作為參數(shù)傳遞給函數(shù)的時候, 傳遞的是數(shù)組的首地址, 傳遞地址, 形參是指針;

數(shù)組參數(shù)示例:

--函數(shù)參數(shù)是數(shù)組: 函數(shù)傳入一個字符串?dāng)?shù)組參數(shù), 返回這個字符串長度;

[cpp]view plaincopy
  1. /*************************************************************************
  2. >FileName:array_param.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Sat15Mar201412:46:57AMCST
  6. ************************************************************************/
  7. #include
  8. //計算字符串長度
  9. intstrlen(char*s)
  10. {
  11. intn;
  12. for(n=0;*s!=