Double pointer · parallel_processing
文章推薦指數: 80 %
陣列的指標(pointer to array) 以及二維陣列(two dimensional array) 的基本用法: ... 簡單的說,它是一個一維陣列,每個元素放的是char *指標,指向字串"Hello"與"C".
parallel_processing
Introduction
程序/行程(Process)
平行處理系統類別
MPI(Messagepassinginterface)
MPICH安裝與設定
點對點通訊
集合通訊
Communicator
One-sidedcommunication
TORQUE
OpenMP
OpenMP設定
pthread
ApacheSpark
Spark安裝與設定
RDD介紹
基本程式設計
HDFS
MapReduce介紹
CUDA
安裝(installation)
第一個程式
PyCUDA
Theano
Tensorflow
XORproblem
Cython
編譯
平行處理
PEP
numpy
Pandas
C語言語法
Clibrary
Pointer
Doublepointer
Functionpointer
Struct
Memoryleak
C++參考
C++物件
C++樣版
x86函式調用協定
編譯器參數
cmake
Pythonclass設計
nosetest
py.test
BLASlibrary
Linpackbenchmark
PoweredbyGitBook
Doublepointer
雙層指標(doublepointerorpointerofpointer)
intnum=123;
int*pr2=#
int**pr1;=&pr2;
雙層指標(doublepointer),這種資料格式很容易和指標陣列、陣列的指標、以及二維陣列三種型態混淆。
會有此不同解釋的差異是因為*運算子的優先權
int*arr1[10];//長度為10的指標陣列
int*(arr2[10]);//同上,長度為10的指標陣
int(*arr3)[10];//指標指向長度為10的陣列,若有5列(5個指標)時,等價於intarr3[5][10];
雙層指標基本用法:
int**ppData=NULL;
int*pData=NULL;
intdata=0;
ppData=&pData;
pData=&data;
**ppData=10;//在變數data內存入數值資料10
陣列的指標(pointertoarray)以及二維陣列(twodimensionalarray)的基本用法:
陣列的指標是指有許多指標,每個指標指向固定長度的陣列
/*pointertoarrayof20integers
*這邊*pAry是指向每個row的第一個元素,而每個row有20個元素
*因此pAry[i][j]等於*(*(pAry+i)+j)
*/
int(*pAry)[20];
intx[10][20];
ppData=x;//ERROR:cannotconvertint[20]*toint**
pAry=x;//OK:sametype
pAry[5][10]=100;//將數值100置於變數x[5][10]之內
//等價於*(*(pAry+5)+10)=100
指標陣列(pointerarray)的基本用法
指標陣列為型態為指標的陣列
int*ptrAry[20];//pointerarray,即為20個指標的array,如同doublearr[20];
ppData=ptrAry;//OK:sametype
ppData[13]=&data;//將變數data的位址存放到變數ptrAry[13]中
cdecl解釋
上述複雜的情形,可使用cdecl程式解釋,首先安裝sudoapt-getinstallcdecl
進入cdecl環境中,輸入
cdecl>explainint*arr1[8];
declarearr1asarray8ofpointertoint
cdecl>explainint(*arr2)[8]
declarearr2aspointertoarray8ofint
cdecl>explainint*(arr3[8])
declarearr3asarray8ofpointertoint
二維陣列和字串陣列
二維陣列和字串陣列是個很類似的東西。
/*names1為字串陣列,names2為二維陣列*/
char*names1[]={"Hello","C"};//sizeof(names1)=8
charnames2[][6]={"Hello","C"};//sizeof(names2)=12
names1是一個字串陣列,簡單的說,它是一個一維陣列,每個元素放的是char*指標,指向字串"Hello"與"C"
重點是,"Hello"與"C"這兩個字串並不存在陣列裡,而是存在記憶體的其他地方。
也可解釋為這個兩個指標所形成的陣列。
names2是一個二維陣列,簡單的說,字串是儲存在陣列裡,也由於他是儲存在陣列裡,所以必須考慮到最長的字串長度,雖然第二個元素"C"只有1byte再加上'\0'共2byte,"Hello"加上'\0'共6byte,為了考慮最長字串6byte,導致names的column長度要宣告到6byte,很明顯地,這對第一個元素"C"浪費了4byte,但字串陣列就沒這個缺點。
指標在函數中改方向時必須以doublepointer參數傳遞
如要在函式裡面改變變數a的值時,引數必須為pointer,然後傳入&a一樣。
如果要在函式裡面改變pointerp的值,則引數必須為doublepointer,然後傳入&p。
voidfoo1(int*q,int&v){
q=&v;
}
voidfoo2(int**q,int&v){
*q=&v;
}
intmain(){
inti=10,j=20;
int*p=&i;
foo(p,&j);
printf("*p=%d\n",*p);//p=10,值沒有改變
foo2(&p,&j);
printf("*p=%d\n",*p);//p=20;
return0;
}
在foo1裡面,我們有一個local的pointerq。
當呼叫foo1時,實際上我們把p的內容,拷貝給q。
所以q也指向i。
譬如說,&i的位址假設是0×1234,p裡面的內容就是0×1234。
所以呼叫foo1的時候,p的內容被拷給q,而p被丟入stack中。
當你改變q的值時,p並沒有受到影響。
所以當程式返回之後,p的值還是0×1234。
指標以函數參數傳遞時,仍是copybyvalue。
在foo2裡面,情況則不一樣。
傳入foo2裡面的是p的位址。
所以當你改變*q的時候,會改變p的指向。
使用doublepointer接住傳遞來的位址。
Pointer與多維陣列
array並非pointer,但array可以自動轉型成pointer,這也是array傳進function後變成pointer的理論基礎
inta[2][4]={{1,3,5,7},{2,4,6,8}};
陣列表示法
值
連續記憶體表示法
陣列索引值轉換表示法
a[0][0]
1
**a
((a+0)+0)
a[0][1]
3
(a+1)
((a+0)+1)
a[1][0]
2
(a+4)
((a+1)+0)
a[1][3]
8
(a+7)
((a+1)+3)
二維陣列
二維陣列使用陣列名稱與兩個索引值來指定存取陣列元素,這兩個索引值都是由0開始。
C語言存放二維或維度更高的陣列是以row-major方式儲存(fortran是columnmajor)
ccompiler在編譯時會將高維的陣列轉回一維。
以二維陣列arr有N_ROW列,N_COL行,則arr[idx][jdx]以row-major轉回一維索引即為idx*N_ROW+jdx.
#include
printf("alocation:%p\n",a);
printf("a[0][0]:%p\n",&a[0][0]);
printf("ptr[0]:%p\n",ptr[0]);
printf("a[1][0]:%p\n",&a[1][0]);
printf("ptr[1]:%p\n",ptr[1]);
return0;
}
//output
alocation:0x7ffd8e57cb50
a[0][0]:0x7ffd8e57cb50
ptr[0]:0x7ffd8e57cb50
a[1][0]:0x7ffd8e57cb64
ptr[1]:0x7ffd8e57cb64
return0;
}
函數參數必須指定column的長度
voidfoo1(intx[][]){//編譯成功,但Compiler不知如何翻譯,還是用int*x自己計算地址比較好
x[2][2]=0;//編譯錯誤!,Compiler不知如何翻譯
}
voidfoo2(intx[][3]){//Compiler知道如何翻譯
x[1][1]=0;//Compiler知道要翻成*(x+1*3+1)
}
voidfoo3(intx[2][3]){//Compiler知道如何翻譯
x[1][1]=0;//Compiler知道要翻成*(x+1*3+1)
}
voidfoo4(intx[3][]){//編譯錯誤
}
voidfoo5(int*x){//反正只能傳pointer
*(x+1*3+1)=0;
}
intmain(){
intm[2][3];
int*p;
intk[4][4];
foo2(m);
foo2(p);//Compilerwarning,incompatiblepointertype
foo3(k);//Compilerwarning,incompatiblepointertype
foo5(m);//Compilerwarning,incompatiblepointertype
foo5(p);
foo5((int*)m);//強迫轉型,Compiler就不會抱怨了
}
動態配置二維陣列
非連續記憶體:缺點是memoryfragment。
constintsizex=2;
constintsizey=3;
intx,y;
int**ia=(int**)malloc(sizey*sizeof(void*));
for(y=0;y!=sizey;++y)
ia[y]=(int*)malloc(sizex*sizeof(int*));
//operations
for(y=0;y!=sizey;++y)
free(ia[y]);
free(ia);
連續記憶體
//此版本仍然釋放二次,不完善
constintsizex=3;
constintsizey=2;
intx,y;
int**ia=(int**)malloc(sizey*sizeof(void*));
//將第二個陣列所需的記憶體一次malloc()
int*iax=(int*)malloc(sizey*sizex*sizeof(int*));
for(y=0;y!=sizey;++y,iax+=sizex)
ia[y]=iax;
...
free(ia[0]);
free(ia);
constintsizex=3;
constintsizey=2;
intx,y;
int**ia=(int**)malloc(sizey*sizeof(void*)+sizey*sizex*sizeof(int*));
int*iax=(int*)(ia+sizex);
for(y=0;y!=sizey;++y,iax+=sizex)
ia[y]=iax;
...
free(ia);
二維陣列非連續配置記憶體
C語言可以使用arraystyle的方式將二維陣列傳入函數,可以同時提供rowsize與columnsize,也可省略rowsize只提供columnsize。
C語言可以將二維陣列用pointer如傳遞一維陣列方式傳入函數,在某些場合使用一維陣列操作方式可能更加方便。
當C語言的二維陣列以pointer型態傳入函數時,必須要使用包含columnsize的一維陣列的pointer。
//因為n_row與n_col都是變數,所以必須使用此方式才能傳進function
voidsub(int**matrix,introw_size,intcol_size);
/*如果n_row與n_col為定值時,可使用以下的函式簽名
voidsub(intmatrix[][n_col]);
orvoidsub(int(*matrix)[n_col]);
注意仍不可指定n_row之值
*/
intmain(){
intx,y;
scanf("%d%d",&x,&y);
int**matrix=calloc(y,sizeof(int*));
for(inti=0;i
延伸文章資訊
- 1二維陣列與雙重指標 - 程式人生
一、簡介. 1、二維陣列. int array[10][10]; 函式宣告: void fun(int a[][10]) 函式呼叫:fun(array); 訪問: 一般使用a[i][j]來訪問陣...
- 2[C語言] - 指標及多維陣列 - Ivan's Blog
指標及一維陣列在不少的書籍,我們都可以看到可以把陣列看成指標,這不完全正確,但在實作上也不能說完全不正確本質上陣列名稱代表的是一個位址, ...
- 3Double pointer · parallel_processing
陣列的指標(pointer to array) 以及二維陣列(two dimensional array) 的基本用法: ... 簡單的說,它是一個一維陣列,每個元素放的是char *指標,指向...
- 4[console] 二維陣列與指標@ 藍影
- 5指標的指標
記憶體位址就單純是個值,若只是單純想儲存記憶體位址,使用void* 型態的指標就可以了。 ... 一維陣列變數的元素位址可以儲至 int* 指標,那二維陣列呢?在〈二維( ...