二級(jí)指針做輸入的三種內(nèi)存模型

二級(jí)指針作輸入,有三種內(nèi)存模型,以字符型指針為例:

第一種內(nèi)存模型:

1、char *pointer[10],pointer自動(dòng)退化為一個(gè)二級(jí)指針,其實(shí)質(zhì)是char **pointer。這種用法是指針數(shù)組的用法,編譯器在棧區(qū)分配內(nèi)存。

需要掌握:1、排序;2、指針做函數(shù)參數(shù)排序;3、畫(huà)出內(nèi)存分配圖。

void main21()

{

int i=0, j=0;

int num = 0;

char * tmp=NULL; //輔助指針變量

char * myArray[10]={"aaa", "bbb", "ccc", "111"};

//打印

printf("排序前\n");

num = sizeof(myArray)/sizeof(myArray[0]); // 對(duì)數(shù)組求長(zhǎng)度;

for (i=0; i<num; i++)

{

? ? printf("%s \n", myArray[i]);

? ? //printf("%s \n", *(myArray+i)); 兩種方式都可以

}

//排序1,交換數(shù)組元組,即交換指針而非內(nèi)存。

for (i=0; i<num; i++)

{

? ? for (j=i+1; j<num; j++)

????{

? ? ? ? if (strcmp(myArray[i], myArray[j])>0)

????????{

? ??????????? tmp = myArray[i];

? ? ? ? ? ? ? myArray[i] = myArray[j];

? ? ? ? ? ? ? myArray[j] = tmp;

????????}

????}

}

//打印

printf("排序后\n");

for (i=0; i<num; i++)

{

????printf("%s \n", myArray[i]);

????//printf("%s \n", *(myArray+i)); 兩種方式都可以

}

}

////////指針做函數(shù)參數(shù)


void printMyArray11(char **myArray, int num) //數(shù)組做函數(shù)參數(shù),會(huì)退化為指針,因此需要將數(shù)組長(zhǎng)度傳進(jìn)來(lái)。

{

int i=0;

for (i=0; i<num; i++)

{

printf("%s \n", myArray[i]);

//printf("%s \n", *(myArray+i)); 兩種方式都可以

}

} //printMyArray11

void sortMyarray12(char **myArray, int num)

{

int i=0, j =0;

char * tmp=NULL;

for (i=0; i<num; i++)

{

for (j=i+1; j

????{

????????if (strcmp(myArray[i], myArray[j])>0)

????????{

????????????tmp = myArray[i];

? ? ? ? ? ? myArray[i] = myArray[j];

????????????myArray[j] = tmp;

????????}

????}

}

} // sort end

void main()

{

int i=0, j=0;

int num = 0;

char * tmp=NULL; //輔助指針變量

char * myArray[10]={"aaa", "bbb", "ccc", "11111"};

//打印

printf("排序前\n");

num = sizeof(myArray)/sizeof(myArray[0]); // 對(duì)數(shù)組求長(zhǎng)度;

printMyArray11(myArray, num);

//排序1,交換數(shù)組元組,即交換指針而非內(nèi)存。

sortMyarray12(myArray, num);

//打印

printf("排序后\n");

printMyArray11(myArray, num);

}

第一種內(nèi)存模型,內(nèi)存分配圖:指針數(shù)組在棧區(qū),字符串在常量區(qū),交換指針數(shù)組達(dá)到排序的目的。因?yàn)樽址诔A繀^(qū),故不能通過(guò)交換內(nèi)存的方式進(jìn)行排序。

第二種內(nèi)存模型:

2、char pointer[10][30]={“hello”, "world", "Tony"}; 字符串存儲(chǔ)在常量區(qū),并拷貝到棧區(qū),結(jié)尾附帶'\0'。高位維數(shù)必須指定。這種用法決定了數(shù)組名+1的步長(zhǎng)。實(shí)參數(shù)組名+1的步長(zhǎng)為第二維個(gè)char單位;形參若使用char ** 接收,步長(zhǎng)xxx;形參若用char [][]接收, 形參+1步長(zhǎng)為第二維個(gè)char單位。

第二種內(nèi)存模型和第一種內(nèi)存模型不同的是,1、第一種內(nèi)存模型排序時(shí),改變的是指針的指向,第二種是交換內(nèi)存塊;2、兩者的形參的數(shù)據(jù)類(lèi)型不一樣,導(dǎo)致指針的步長(zhǎng)不一樣。(猜想可能由于棧區(qū)的內(nèi)存塊大小不一樣所致。)3、兩者的內(nèi)存四區(qū)分配不一樣。第一種在棧區(qū)分配內(nèi)存存儲(chǔ)指針數(shù)組,數(shù)組元素指向靜態(tài)區(qū)的字符串;第二種在棧區(qū)分配內(nèi)存,將靜態(tài)區(qū)的字符串全部拷貝到棧區(qū)(拷貝包括字符串結(jié)尾符‘\0’),同時(shí)靜態(tài)區(qū)保留一份備份。

兩種內(nèi)存模型的數(shù)據(jù)類(lèi)型,做函數(shù)參數(shù)時(shí)牽扯到多級(jí)指針的退化問(wèn)題,需特別注意形參定義的不同。

需掌握:打印、排序、封裝成函數(shù);

void main31()

{

? ? int i=0, num =4;

? ? char myBuf[30];

? ? char tmpBuf[30];

? ? char myArray[10][30]={"aaaaaa", "cccc", "bbbbb", "11111111"};

// 打印

printf("排序前");

? ? for (i=0; i<num; i++)

????{

? ? printf("%s\n", myArray[i]);

????}

// 排序

for (i=0; i<num; i++)

{

? ? for (j=i+1; j<num; j++)

????{

? ? ? ? if ( strcmp(myArray[i], myArray[j])>0 )

????{

? ? strcpy(tmpBuf, myArray[i]);

? ??strcpy(myArray[i], myArray[j]);

? ??strcpy(myArray[j], tmpBuf);

????}

????}

}

// 打印

printf("排序后");

for (i=0; i<num; i++)

????{

????printf("%s\n", myArray[i]);

????}

}


//封裝成函數(shù)

void main()

{

int i=0, num =4;

char myBuf[30];

char tmpBuf[30];

char myArray[10][30]={"aaaaaa", "cccc", "bbbbb", "11111111"};

// 打印

printf("排序前");

// printMyArray21_1(myArray, num); // 程序download掉

printMyArray21_2(myArray, num);? // 程序正常

// 排序

sortMyarray21(myArray[10][30], num);?

// 打印

printf("排序后");

// printMyArray21_1(myArray, num); // 程序download掉

printMyArray21_2(myArray, num);? // 程序正常

}


void printMyArray21_1(char **myArray, int num)?

{

int i=0;

for (i=0; i<num; i++)

{

// printf("%s \n", myArray[i]);//??

printf("%s \n", *(myArray+i)); // 問(wèn)題本質(zhì):二級(jí)指針輸入的第二種內(nèi)存模型的 myArray+1? 和第一種內(nèi)存模型的 myArray+1 不一樣,即指針?biāo)赶虻膬?nèi)存空間的數(shù)據(jù)類(lèi)型不一樣,導(dǎo)致指針的步長(zhǎng)不一樣,導(dǎo)致第二種內(nèi)存模型 myArray+1非法的內(nèi)存訪問(wèn)。這種問(wèn)題是多級(jí)指針做函數(shù)參數(shù)的退化問(wèn)題。解決辦法如:形參char **myArray 改為char myArray[10][30]。后續(xù)有更好的處理方法。

}

} //printMyArray21_1

void printMyArray21_2(char **myArray, int num)

{

int i=0;

for (i=0; i<num; i++)

{

// printf("%s \n", myArray[i]);//??

printf("%s \n", *(myArray+i)); // 多級(jí)指針做函數(shù)參數(shù)的退化問(wèn)題。解決辦法如:形參char **myArray 改為char myArray[10][30]

}

} //printMyArray21_2

void sortMyarray21(char myArray[10][30], int num)

{

int i, j =0;

char tmpBuf[30];

for (i=0; i<num; i++)

{

for (j=i+1; j<num; j++)

????{

if ( strcmp(myArray[i], myArray[j])>0 )

????{

strcpy(tmpBuf, myArray[i]);? // 交換的是內(nèi)存塊。

strcpy(myArray[i], myArray[j]);

strcpy(myArray[j],?tmpBuf);

????}

????}

}

}


第三種內(nèi)存模型:

3、char **pointer是第三種內(nèi)存模型??傊羔樤跅^(qū),數(shù)組元素即一維指針在堆區(qū),一維指針的指向的元素也在堆空間。

void main03()

{

int i = 0, j=0;

char ** p2 = NULL;

int num=5;

char * tmp;

char tmpbuf[100];

p2=(char **)malloc(sizeof(char)*num);

for (i=0;i<num;i++)

{

p2[i]=(char *)malloc(sizeof(char) * 100); //定義了num個(gè)buf[100]

sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);//sprintf(),將字符串輸入到p2中。

} //for end

//排序之前:

for (i=0;i<num;i++)

{

printf("%s \n", p2[i]);

}//for end


//排序,交換指針指向;

/*

for (i=0;i<num;i++)

{

for (j=i+1;j<num;j++)

{

if(strcmp(p2[i], p2[j])<0)

{

tmp=p2[i];

p2[i]=p2[j];

p2[j]=tmp;

}

}//for end

}//for end

*/

//排序,交換內(nèi)存:

for (i=0;i<num;i++)

{

for (j=i+1;j<num;j++)

{

if(strcmp(p2[i], p2[j])<0)

{

strcmp(tmpbuf, p2[i]);

strcmp(p2[i], p2[j]);

strcmp(p2[j], tmpbuf);

}

}//for end

}//for end


// 釋放內(nèi)存:先申請(qǐng)的后釋放。

for (i=0;i<num;i++)

{

if(p2[i]!=NULL)

{

free(p2[i]);

p2[i]=NULL;

}

}//for end

if(p2!=NULL)

{

free(p2);

p2=NULL;

}

}//main end


//***************指針做函數(shù)參數(shù)***************

char **getMem(int num)

{

char **p2=NULL;

int i;

p2=(char **)malloc(sizeof(char*) * num); // num=5個(gè)(char * )類(lèi)型大小的空間,即4*5=20個(gè)字節(jié),32位系統(tǒng)。p2+1,步長(zhǎng)為char **個(gè)字節(jié),即4個(gè)字節(jié),因此正好跳到了下一個(gè)“char *”的指針的首地址。

if(p2==NULL)

{

????return NULL;

}

for (i=0;i<num; i++)

{

p2[i]=(char *)malloc(sizeof(char)*100);

sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);

}

return p2;

}//getMem end


void printArray03(char ** myArray, int num)

{

int i=0;

for (i=0;i<num;i++)

{

? //? ? printf("%s\n", myArray[i]);

? printf("%s \n", *(myArray+i));

}

}//printArray03 end

void sortArray03(char ** myArray, int num)? //交換指針和交換內(nèi)存都可?,F(xiàn)在時(shí)交換指針。

{

int i, j=0;

char *tmp=NULL;

for(i=0;i<num;i++)

{

for(j=i+1;j<num;j++)

{

tmp=myArray[i];

myArray[i]=myArray[j];

myArray[j]=tmp;

}

} //for loop end

}//sortArray03 end

void getMemFree(char **p2, int num)

{

// 釋放內(nèi)存:先申請(qǐng)的后釋放。

for (i=0;i<num;i++)

{

if(p2[i]!=NULL)

{

free(p2[i]);

p2[i]=NULL;

}

}//for end

if(p2!=NULL)

{

free(p2);

p2=NULL;

}

}//getMemFree


void main()

{

int i = 0, j=0;

char ** p2 = NULL;

int num=5;

char * tmp;

char?tmpbuf[100];

p2=getMem(num);//分配內(nèi)存

//排序之前:

printArray03(p2, num);

sortArray03(p2, num);

//排序,交換指針指向;

/*

for (i=0;i<num;i++)

{

for (j=i+1;j<num;j++)

{

if(strcmp(p2[i], p2[j])<0)

{

tmp=p2[i];

p2[i]=p2[j];

p2[j]=tmp;

}

}//for end

}//for end

*/

//排序,交換內(nèi)存:

/*

for (i=0;i

{

for (j=i+1;j<num;j++)

{

if(strcmp(p2[i], p2[j])<0)

{

strcmp(tmpbuf, p2[i]);

strcmp(p2[i], p2[j]);

strcmp(p2[j], tmpbuf);

}

}//for end

}//for end

*/

//排序后

printArray03(p2, num);

// 釋放內(nèi)存:先申請(qǐng)的后釋放。

getMemFree(p2,num);//注意,此時(shí)p2是野指針!

}//main end


第一種內(nèi)存模型:指針數(shù)組;第二種內(nèi)存模型:多維數(shù)組;第三種內(nèi)存模型:自己分配內(nèi)存;

第三種內(nèi)存模型:交換指針排序和交換內(nèi)存空間排序都可以;打?。嚎梢詮?fù)用第一種內(nèi)存模型的api函數(shù);注意使用函數(shù)釋放空間時(shí),可能造成實(shí)參野指針現(xiàn)象!


留下的疑問(wèn):1、第二種內(nèi)存模型,調(diào)用函數(shù)時(shí),函數(shù)形參的形式;2、第二種內(nèi)存模型,調(diào)用函數(shù)時(shí),形參的步長(zhǎng)?實(shí)參的步長(zhǎng)?3、一維或多維數(shù)組做函數(shù)參數(shù)時(shí)的退化問(wèn)題,及其步長(zhǎng)問(wèn)題;4、第三種內(nèi)存模型,free內(nèi)存函數(shù)易造成實(shí)參野指針,如何避免?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容