20160211.CCPP體系詳解(0021天)
程式片段(01):01.指標陣列.c+02.動態陣列.c
內容概要:指標陣列
///01.指標陣列.c
#include <stdio.h>
#include <stdlib.h>
//01.指標陣列作為函式的形參:
// 會退化為一個二級指標!
//02.如何確定一個陣列作為函式形參將會退化為什麼樣兒的指標?
// 關鍵在於形引數組當中的元素是什麼型別!就是什麼型別的指標
void show01(char * str[5])//char *str[5]
{
for (int i = 0; i < 5; ++i)
{
printf("%s \n", str[i]);//char **str
}
}
//03.等價關係:
// 二級指標和指標陣列的陣列名所對應的解析方式都一樣!
void show02(char ** str)
{//指標陣列作為函式的形參進行傳參的時候,指標陣列的陣列名將會退化為一個二級指標!
for (int i = 0; i < 5; ++i)
{
printf("%s \n", str[i]);
}
}
//04.函式形參的攔截機制:
// 如果是陣列,就沒有副本機制,不是副本,就有攔截介質
//注:解除陣列的副本機制依賴於陣列名的退化機制!
//05.如何確定一個變數的資料型別?
// 在定義變數的基礎情況之下,挖掉變數名,就是變數的資料型別
//注:字元指標陣列開發過程當中比較常用!
int main01(void)
{
int * arr[10];//-->int * [10]-->一級指標陣列型別!
//一級指標陣列的陣列名arr在作為函式形參的時候,該一級指標的陣列名會自動退化以為一個二級指標
char * str[5] = { "calc", "notepad", "tasklist", "mspaint", "pause" };
//char * [N]:字元指標型別的一級指標陣列在開發過程當中經常使用!
char **pp = str;//變數指標=常量指標(地址意義的陣列賦值動作!)-->指標變數結果-->指標變數遍歷!
printf("%p \n", str);//二級指標常量的數值
//show01(str); <= = > show02(str);
system("pause");
}
///02.動態陣列.c
#include <stdio.h>
#include <stdlib.h>
//01.如何確定動態陣列的陣列名稱?
// 1.開闢記憶體的時候所採用的指標變數名稱就是動態陣列名稱!
// 2.通過指標變數名稱的訪問方式就如同標準陣列的訪問方式!
// 注:嚴格區分變數指標和常量指標之間的差別!
int main02(void)
{
//動態分配一個一維陣列
int * const arr = malloc(30 * sizeof(int));
for (int i = 0; i < 30; ++i)
{
printf("%d \n", arr[i] = i);//arr[i]<=>*(arr+i)
}
system("pause");
}
//02.動態陣列的分配要點:
// 1.動態記憶體開闢函式!
// 2.解析動態記憶體的指標型別!
// 注:所有陣列都看做為一維陣列!,指向該陣列首元素的指標
// 指標可以使用:變數指標和常量指標(模擬棧記憶體陣列!)
// 注:動態陣列的尺寸在程式執行過程當中決定!
// 每個當前維度的陣列都必須要求明確其維度-1的特點
int main03(void)
{
//動態分配一個二維陣列
//int test = 5;
int(*p)[5] = malloc(30 * sizeof(int));
for (int i = 0, num = 0; i < 30; ++i, ++num)
{
printf("%3d", p[i / 5][i % 5] = num);//0->1->2->3...
if (0 == (i + 1) % 5)
putchar('\n');
}
system("pause");
}
//03.兩種區別的陣列:
// 二維陣列:陣列當中的每個相鄰陣列元素的記憶體地址必須連續
// (連續!+對齊!)
// 分塊陣列:針對於同一個陣列當中的每個陣列元素的記憶體地址必須連續
// 但是內部就整體而言的陣列元素之間是可以不連續的
// (不連續+不對齊!)
// 注:動態記憶體開闢函式的返回值型別為("void *")型別,只是負責返回一個有效
// 地址,但是沒有具備解析意義+堆記憶體動態開闢函式前面的賦值號只是用於
// 返回一個明確的地址而已!-->指標型別決定對動態記憶體的實際解析意義!
int main04(void)
{
//使用malloc函式在堆記憶體當中開闢一個指標陣列!
int **pp = malloc(5 * sizeof(int *));//20個堆記憶體位元組
int num = 0;
for (int i = 0; i < 5; ++i)
{
pp[i] = (int *)malloc((5 + i)*sizeof(int));
for (int j = 0; j < 5 + i; ++j)
{
pp[i][j] = num++;//賦值
}
}
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5 + i; ++j)
{
printf("%3d", pp[i][j]);
}
printf("\n");
}
system("pause");
}
//04.常見資料結構的特點:
// 陣列:查詢效率高+增加|刪除效率低
// 連結串列:增加|刪除效率高+查詢效率低
// 分塊:查詢效率和陣列一樣+增加|刪除效率比陣列高(略低於連結串列,不過可以忽略!)
// 可以不用連續,可以不用對齊!
//05.如何分配一個N-1級指標陣列?
// 需要一個N級的指標!
// N級指標,儲存N-1級指標陣列的地址
// N級指標分配一個陣列,用於存放N-1級指標陣列的首個元素的地址(區分變數指標|常量指標)
// 資料等同於0級指標
程式片段(02):01.Array.c
內容概要:陣列的三種形態
#include <stdio.h>
#include <stdlib.h>
//01.C語言版本標準:
// 第一版:C89
// 第二版:C99
//02.(VC2013以上+GCC4.7以上)支援C99語法
// VC2013+GCC4.7
//03.C99新語法分配陣列模式!
// 1.位於棧記憶體的靜態陣列
// 2.可以進行指明初始化!
// 指明初始化的最大索引可以推導陣列總元素個數
// 3.指明初始化方式的特點:可以明確長度!
// 純大括號初始化:只能同時指明陣列長度,並且給陣列最後一個元素初始化賦值
// 其餘陣列元素統統採用預設初始化方式!
// 非純大括號初始化:可以同時指明陣列長度,並且給多個陣列元素初始化賦值
// 其餘陣列元素統統採用預設初始化方式!
int main01(void)
{
int arr[] = { [10] = 10 };//預設不操作的陣列元素被賦值為0,[10]-->arr[10]=0->11個元素
for (int i = 0; i < 11; ++i)
{
printf("%d \n", arr[i]);
}
system("pause");
}
int main02(void)
{
int n = 4;
int * pC99 = (int[]) { [2] = 1, [4] = 10 };//靜態陣列
//預設不指明初始化的陣列元素所對應的值為0
for (int i = 0; i < 5; ++i)
{
printf("%d \n", pC99[i]);
}
system("pause");
}
//04.靜態陣列與動態陣列:
// 靜態陣列:
// 1.儲存於棧記憶體
// 2.編譯時期決定陣列元素個數
// 3.(自動開闢+自動回收)
// 動態陣列:
// 1.儲存於堆記憶體
// 2.執行時期決定陣列元素個數
// 3.(手動開闢+手動釋放)
// 注:嚴格區分(分配+釋放)以及(開闢+回收)的區別
// 分配+釋放:許可權
// 開闢+回收:記憶體
void run()
{
//int arr[5] = { 1, 2, 3, 4, 5 };
int * p = malloc(10 * sizeof(int));
for (int i = 0; i < 10; ++i)
{
p[i] = i;//p[i]-->*(p+i)
}
free(p);
//基於C99語法的靜態陣列:處於棧記憶體當中,自動開闢回收,用於解決心臟起搏器問題!
//int * pC99 = (int []){ [4] = 10 };
//printf("%p \n", pc99);
printf("\n");
}
int main03(void)
{
run();
printf("\n\n\n");//加速記憶體的回收動作!+防止Release模式!優化操作
run();
printf("\n\n\n");
system("pause");
}
//05.指標變數可以指向任何記憶體地址:
// 無論是棧記憶體,堆記憶體,全域性區,程式碼區
int main04(void)
{
int num = 30;
//int * pC99 = (int[30]) { 0 };
//pC99 = (int[10]) {0};//pC99是int*型別
//pc99 = 1;
int * pC99 = (int [30]) { [2] = 1, [4] = 10 };//靜態陣列
for (int i = 0; i < 30; ++i)
{
printf("%d \n", pC99[i]);
}
system("pause");
}
//06.區分靜態分配和動態分配區別:
// int num=30;//靜態分配:必須在編譯時期,決定靜態陣列的元素個數
// int a[num];//棧上的靜態分配-->可變長度的陣列只有在GCC編譯器當中實現,VC編譯器當中不能進行實現
// 注:VC不支援位於棧記憶體的靜態陣列+GCC支援位於棧記憶體的靜態陣列!
程式片段(03):01.記憶體.c
內容概要:四大分配堆記憶體的函式
#include <stdio.h>
#include <stdlib.h>
//01.記憶體四大分配函式:
// malloc<->calloc:
// malloc:記憶體不清零(引數:記憶體位元組數)
// calloc:記憶體清零(引數1:陣列元素個數+引數2:單個元素尺寸)
// realloc<->_recalloc:
// realloc:記憶體不清零(引數1:記憶體首地址,總記憶體位元組數)
// 1.如果原始記憶體地址足夠擴充,就在原始記憶體地址進行擴充
// 2.如果原始記憶體地址不夠擴充,就在新地址記憶體進行擴充:
// 拷貝原始記憶體地址所對應的有效資料+回收原始記憶體地址資料
// 3.擴充之後的記憶體如果沒有資料進行覆蓋,就不回執行記憶體清零操作!
// _recalloc:記憶體清零(引數1:記憶體首地址+引數2:陣列元素個數+引數3:單個元素尺寸)
// 1.如果原始記憶體地址足夠擴充,就在原始記憶體地址進行擴充
// 2.如果原始記憶體地址不夠擴充,就在新地址記憶體進行擴充
// 拷貝原始記憶體地址所對應的有效資料+回收原始記憶體地址資料
// 3.擴充之後的記憶體如果沒有進行手動初始化,系統將會執行自動初始化操作!
int main01(void)
{
//int * p = (int *)malloc(100);//malloc不會初始化引數,引數是整體所佔用的記憶體尺寸(位元組數)!
int * p = calloc(25, sizeof(int));//calloc存在初始化引數,引數解釋:第一個引數是元素個數,第二個引數是元素記憶體尺寸
printf("%p \n", p);
//for (int i = 0; i < 25; ++i)
//{
// p[i] = i;
//}
system("pause");
}
int main02(void)
{
int * p = malloc(10 * sizeof(int));//指標能夠操作這片兒堆記憶體!
//int * p_p = malloc(100);
for (int i = 0; i < 10; ++i)
{
printf("%d \n", p[i] = i);
}
printf("p = %p \n", p);
int * px = realloc(p, 200);//擴充記憶體,記憶體不清零
//返回值是記憶體首地址,說明擴充成功,後續地址擴充,擴充不成功,重新開闢記憶體
//原來的記憶體就被回收了
printf("px = %p \n", px);
for (int i = 0; i < 50; ++i)
{
px[i] = i;
printf("%d \n", px[i]);
}
//p[120387] = 10;
system("pause");
}
int main03(void)
{
int * p = calloc(25, sizeof(int));//會初始化為0,引數:陣列元素個數+記憶體位元組大小
//scanf("123");
printf("%p \n", p);
for (int i = 0; i < 25; ++i)
{
p[i] = i;
}
p = _recalloc(p , 50, sizeof(int));//記憶體清零操作
for (int i = 25; i < 50; ++i)
{
p[i] = i;
}
system("pause");
}
程式片段(04):main.c
內容概要:GccArray
#include <stdio.h>
#include <stdlib.h>
//01.VC不支援棧記憶體動態陣列,GCC支援棧記憶體動態陣列!
int main()
{
int num=30;
int a[num];//棧上的動態分配
//int *pc99 = (int[30]){0};
//printf("Hello world!\n");
return 0;
}
相關文章
- 20160217.CCPP體系詳解(0027天)
- 20160124.CCPP詳解體系(0003天)
- 20160125.CCPP詳解體系(0004天)
- 20160126.CCPP體系詳解(0005天)
- 20160127.CCPP體系詳解(0006天)
- 20160130.CCPP體系詳解(0009天)
- 20160203.CCPP體系詳解(0013天)
- 20160213.CCPP體系詳解(0023天)
- 20160214.CCPP體系詳解(0024天)
- 20160215.CCPP體系詳解(0025天)
- 20160224.CCPP體系詳解(0034天)
- 20160218.CCPP體系詳解(0028天)
- 20160219.CCPP體系詳解(0029天)
- 手遊《天地劫》的三天體驗——深度系統剖析及玩法詳解
- 20160122.CCPP詳解體系(0001天)
- 20160123.CCPP詳解體系(0002天)
- 20160128.CCPP體系詳解(0007天)
- 20160129.CCPP體系詳解(0008天)
- 20160131.CCPP體系詳解(0010天)
- 20160204.CCPP體系詳解(0014天)
- 20160205.CCPP體系詳解(0015天)
- 20160210.CCPP體系詳解(0020天)
- 20160212.CCPP體系詳解(0022天)
- 20160207.CCPP體系詳解(0017天)
- 20160225.CCPP體系詳解(0035天)
- 20160226.CCPP體系詳解(0036天)
- 20160227.CCPP體系詳解(0037天)
- 20160222.CCPP體系詳解(0032天)
- 20160221.CCPP體系詳解(0031天)
- 20160201.CCPP體系詳解(0011天)
- 20160202.CCPP體系詳解(0012天)
- 20160209.CCPP體系詳解(0019天)
- 20160216.CCPP體系詳解(0026天)
- 20160206.CCPP體系詳解(0016天)
- 20160208.CCPP體系詳解(0018天)
- 20160223.CCPP體系詳解(0033天)
- 20160220.CCPP體系詳解(0030天)
- MySQL體系結構詳解MySql