(M2C系列)C語言多元數組初始化
- 一、常用資料類型對照
- 二、一維數組初始化
- 三、多元數組初始化
-
- 1、二維
- 2、三維
- 其他
by HPC_ZY
由于劇情,需要純C(不用三方庫)實作圖像算法。但作為一名MATLAB老使用者,根本不知“指針”“記憶體”為何物。開始自信滿滿,結果連初始化一個二維全零矩陣都不會(尴尬),顧從零學起,在此總結。
今後會持續更新MATLAB函數的C實作,歡迎交流,共同學習。
.
注:C語言博大精深,實作方法衆多。由于本文主題是M2C,是以在方法和格式上會盡量貼近MATLAB。還望各大C佬請勿吐槽。
.
一、常用資料類型對照
MATLAB | C | 位元組數 |
---|---|---|
char | char | 1 |
uint8 | unsigned char | 1 |
uint16 | unsigned short int | 2 |
int32 | int | 4 |
single | float | 4 |
double | double | 8 |
利用sizeof(type)函數可傳回類型的位元組數
/*關于資料類型*/
printf(" MATLAB - C - Byte\n");
printf("( char = char ) %d\n", sizeof(char));
printf("( uint8 = unsigned char ) %d\n", sizeof(unsigned char));
printf("( uint16 = unsigned short int) %d\n", sizeof(unsigned short int));
printf("( int32 = int) %d\n", sizeof(int));
printf("( single = float ) %d\n", sizeof(float));
printf("( double = double ) %d\n", sizeof(double));
二、一維數組初始化
MATLAB
Num = 10;
mat1d1 = zeros(1,Num); % 預設為double
mat1d2 = zeros(1,Num,'uint8');
C
// 記憶體配置設定
int Num = 10;
double mat1d1[10]; // 數組法
unsigned char *mat1d2 = (unsigned char*)malloc(Num * sizeof(unsigned char)); // 指針法
// 值初始化
memset(mat1d1, 0, Num * sizeof(double));
memset(mat1d2, 0, Num * sizeof(unsigned char));
// 檢視
printf("mat1d1:");
for (int k = 0; k < Num; k++)
printf("%.0f ", mat1d1[k]);
printf("\nmat1d2:");
for (int k = 0; k < Num; k++)
printf("%d ", mat1d2[k]);
-
兩種方法寫法的差別
(寫法)
使用數組法時,數組大小隻能使用常量,不能填入變量,如:
double mat[Num]; (此為錯誤)
但數組法可在定義時,賦初始值,如:
int mat[5] = {1,2,3,4,5};
(大小)
數組法記憶體在棧中,空間小,能支援的數組尺寸小;
指針法記憶體在堆中,空間大,能支援大尺寸數組。
是以對于尺寸固定的小數組可使用數組法,其他推薦使用指針法
-
關于memset()函數
三個參數分别為(變量指針,初值,位元組數);
對于uint8類型,初值可設為0~255;
其他類型建議僅在初始值為0時使用menset(),如需賦其他值,可使用for循環。
(具體原因感興趣可自行學習menset()的原理)
-
關于sizeof()
如果熟悉類型的位元組數,可直接寫入,如:
int* mat = (int*)malloc( 10 * sizeof(int) );
int* mat = (int*)malloc( 10 * 4 );
三、多元數組初始化
特别注意指針法記憶體配置設定與賦初值的方式
1、二維
MATLAB
Rows = 2, Cols = 3;
mat2d1 = zeros(Rows,Cols,'int32');
mat2d2 = zeros(Rows,Cols);
C
int Rows = 2, Cols = 3;
// 數組法
int mat2d1[2][3];
memset(mat2d1, 0, Rows * Cols * sizeof(int));
// 指針法
double **mat2d2 = NULL;
mat2d2 = (double**)malloc(Rows * sizeof(double*));
for (int r = 0; r < Rows; r++){
mat2d2[r] = (double*)malloc(Cols * sizeof(double));
memset(mat2d2[r], 0, Cols * sizeof(double));
}
// 檢視略
2、三維
MATLAB
Rows = 2, Cols = 2, Dims = 3;
mat2d1 = zeros(Rows,Cols,Dims,'int32');
mat2d2 = zeros(Rows,Cols,Dims);
C
int Rows = 2, Cols = 2, Dims = 3;
// 數組法
int mat3d1[3][2][2];
memset(mat3d1, 0, Rows * Cols * Dims * sizeof(int));
// 指針法
double ***mat3d2 = NULL;
mat3d2 = (double***)malloc(Dims * sizeof(double**));
for (int d = 0; d < Dims; d++)
mat3d2[d] = (double**)malloc(Rows * sizeof(double*));
for (int d = 0; d < Dims; d++)
for (int r = 0; r < Rows; r++){
mat3d2[d][r] = (double*)malloc(Cols * sizeof(double));
memset(mat3d2[d][r], 0, Cols * sizeof(double));
}
// 檢視略
-
指針法賦初值時,不可直接使用如下格式:
memset(mat2d2 0, Rows * Cols * sizeof(double));
memset(mat3d2 0, Rows * Cols * Dims * sizeof(double));
-
定義三維數組,建議将Dims放第一維。因為做三維圖像處理時,經常需要提取某一幀圖像。如一個尺寸為**V(512, 512, 100)**的體資料,提取第10幀圖像,則
MATLAB: frame10 = V(:, :, 10);
C: double ** frame10 = V[9];
其他
以上僅為使用方案,關于原理不做講述。想深入研究的選手,可自行百度以下内容:
- 資料類型
- 數組
- 指針
- malloc
- memset
- 堆棧