前言:
為啥叫C語言程序猿必會呢?因為特別重要,學習C語言不知道內存分區,對很多問題你很難解釋,如經典的:傳值傳地址,前者不能改變實參,后者可以,知道為什么?還有經典面試題如下:
#include <stdio.h> #include <stdlib.h>
#include <stdlib.h> void getmemory(char *p) { p=(char *) malloc(100); } int main( ) { char *str=NULL; getmemory(str); strcpy(str,"hello world"); printf("%s/n",str); free(str); return 0; }
這段代碼執行了會怎么樣?接下里我會解釋這道面試題。
一、內存布局
可能網上有很多把內存分的很多、很細,但覺得很難記,並對於理解問題作用並不大。現在主要將內存分為四區如下:
代碼區:存放代碼;運行期間不可修改
全局區:全局變量、靜態變量、常量字符串;程序運行時存在,退出時消失。
棧區:自動變量、函數參數、函數返回值;作用域函數內(代碼塊內)
堆區:動態分配內存,需手動釋放
用交換兩個數的程序進行解釋吧,如下:
#include<stdio.h> void swap(int a,int b) { int temp = a; //棧 a = b; b =temp; } int main() { int a=1,b=2; //棧 printf("a:%d,b:%d\n",a,b); swap(a,b); printf("a:%d,b:%d\n",a,b); return 0; }
畫個圖進行講解,如下: PS:依舊是全博客園最丑圖,不接受反駁!

說明:main函數把a,b的值給了temp函數,temp函數在內部交換了值,並沒有影響main函數,並且temp結束,棧上的數據釋放。傳值不會改變實參。
二、程序示例及面試題講解
1、傳地址交換兩個數
在拿傳指針的例子來說明一下,如下:
#include<stdio.h> void swap(int *a,int *b) { int temp = *a; //棧 *a = *b; *b =temp; } int main() { int a=1,b=2; //棧 printf("a:%d,b:%d\n",a,b); swap(&a,&b); printf("a:%d,b:%d\n",a,b); return 0; }
結果:成功交換了實參的值
用圖進行解釋,如下: PS:依舊是全博客園最丑圖,不接受反駁!

說明:實參把地址傳給形參,形參*a、*b是取的實參在內存中的值,交換也就是交換實參的值了,所以成功交換了實參的值。
2、解釋面試題
程序就是最開始的面試題那個,不再列出來了。
結果:段錯誤
然后畫圖進行說明,如下: PS:依舊是全博客園最丑圖,不接受反駁!

說明:最重要一點實參是把值傳給形參,而不是地址,要理解這一點!就是把實參的NULL給了形參,然后getmemory在堆上開辟空間,結束時p被釋放了,但main函數中的str並沒有指向堆上的內存,再給strcpy,當然會段錯誤。
三、解決被調函數開辟空間
可能有人就問了,我就想讓被調函數開空間,怎么辦呢?那就需要形參是二級指針了。
給大家演示一下,代碼如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> void getmemory(char **p) { *p=(char *) malloc(100); } int main( ) { char *str=NULL; getmemory(&str); strcpy(str,"hello world"); printf("%s/n",str); free(str); return 0; }
結果:沒有段錯誤了
大家可以自己畫下圖,不懂歡迎隨時留言。
三、十月份計划
十月份需求會很忙,但也要抽出時間把C++基礎學完,然后深入學習數據結構和算法了
