int **指針與二維數組問題
1)定義二維數組方法:
int matrix[ROWS][COLUMNS]; //定義一個二維數組,其中ROWS和COLUMNS為常數
2)加入有如下聲明的子函數:
void printMatrix(int ** numbers,int rows,int columns);
3)如果直接使用如下方法調用,是錯誤的;
printMatrix(matrix,ROWS,COLUMNS); //直接這樣調用時錯誤的
原因在於matrix是 int (*)[COLUMNS]類型的(即[][]內存連續分配),但是函數printMatrix需要的是int **類型的,這兩者明顯不匹配。
int **從類型上講是一個指向整型指針的指針,用它來表示一個矩陣,實現代碼如下:
int ** generateMatrix(int rows,int columns) { int **numbers=new int*[rows]; for(int i=0;i<rows;i++){ numbers[i]=new int[columns]; for(int j=0;j<columns;j++) numbers[i][j]=i*columns+j; } return numbers; }
把int*當做一個整體。它表示創建了一個大小為rows的數組,這個數組的每一個元素代表一個指針。內存布局如下:
這里numbers是一個指向指針的指針,能夠用numbers用來表示矩陣的關鍵就在於使用new關鍵字分配的內存是連續的,這樣number[i]的地址就可以根據numbers的地址計算出來,因為指針變量占據4個字節的內存區域(32位機器)。如果不使用上面的方式分配內存,numbers就真的只是一個指向指針的指針了
04)正確使用printMatrix(matrix,ROWS,COLUMNS)的測試代碼:
#include <stdlib.h> #include <stdio.h> #include <iostream> //打印矩陣 void printMatrix(int ** numbers,int rows,int columns){ for(int i=0;i<rows;i++) { for(int j=0;j<columns;j++) std::cout<<numbers[i][j]<<" "; std::cout<<std::endl; } } //生成矩陣 int ** generateMatrix(int rows,int columns) { int **numbers=new int*[rows]; for(int i=0;i<rows;i++){ numbers[i]=new int[columns]; for(int j=0;j<columns;j++) numbers[i][j]=i*columns+j; } return numbers; } int main(){ int **numbers=generateMatrix(4,5); printMatrix(numbers,4,5); //釋放內存 for(int i=0;i<4;i++) delete [] numbers[i]; delete numbers; return 0; }
memset()和memcpy()
memset()用法
void *memset(void *s,int c,size_t n)
作用:將已開辟內存空間$s$的首$n$個字節的值設為值$c$(給空間初始化)
C語言需要包含頭文件string.h;C++需要包含cstring 或 string.h
#include <string.h> #include <stdio.h> #include <memory.h> int main(void) { char buffer[] = "Hello world\n"; printf("Buffer before memset: %s\n", buffer); memset(buffer, '*', strlen(buffer) ); printf("Buffer after memset: %s\n", buffer); return 0; }
示例
輸出結果:
Buffer before memset: Hello world
Buffer after memset: ***********
memset() 函數常用於內存空間初始化。如:
char str[100];
memset(str,0,100);
memset()錯誤用法:
int main(void) { char *buffer = "Hello world\n"; printf("Buffer before memset: %s\n", buffer); memset(buffer, '*', strlen(buffer) ); printf("Buffer after memset: %s\n", buffer); return 0; }
報錯原因:char * buffer = "Hello world\n"; 字符串"Hello world\n"存在於只讀存儲區(字面量),其內容不能被隨意更改!!!!
memcpy()函數用法
void *memcpy(void *dest, const void *src, size_t n);
C語言需要包含頭文件string.h;C++需要包含cstring 或 string.h。
用法:用來將src地址處的內容拷貝n個字節的數據至目標地址dest指向的內存中去。函數返回指向dest的指針。
示例1
作用:將s中的字符串復制到字符數組d中
#include <stdio.h> #include <string.h> int main() { char *s="Golden Global View"; char d[20]; clrscr(); memcpy(d,s,( strlen(s)+1) ); printf("%s",d); getchar(); return 0; } //輸出結果:Golden Global View
示例2
作用:將s中第14個字符開始的4個連續字符復制到d中。(從0開始)
#include <string.h> int main() { char *s="Golden Global View"; char d[20]; memcpy(d,s+14,4); //從第14個字符(V)開始復制,連續復制4個字符(View)
//memcpy(d,s+14*sizeof(char),4*sizeof(char));也可 d[4]='\0'; printf("%s",d); getchar(); return 0; } //輸出結果: View
示例3
作用:復制后覆蓋原有部分數據;
#include <stdio.h> #include <string.h> int main(void) { char src[] = "******************************"; char dest[] = "abcdefghijlkmnopqrstuvwxyz0123as6"; printf("destination before memcpy: %s\n", dest); memcpy(dest, src, strlen(src)); printf("destination after memcpy: %s\n", dest); return 0; } //輸出結果: //destination before memcpy:abcdefghijlkmnopqrstuvwxyz0123as6 //destination after memcpy: ******************************as6
注意事項
memcpy用來做內存拷貝,你可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),會造成b的內存溢出。
另外:strcpy只能拷貝字符串,它遇到'\0'就結束拷貝;例:char a[100],b[50]; strcpy(a,b); 如用strcpy(b,a),要注意a中的字符串長度(第一個‘\0’之前)是否超過50位,如超過,則會造成b的內存溢出。會造成緩沖區溢出,輕者程序崩潰,重者系統會出現問題!!
小結
一維數組的動態分配,初始化和撤銷
//動態分配10個空間 int *array=new int [10]; //初始化 memset(array,0,sizeof(array)); //或者 memset(array,0,10*sizeof(int)); //撤銷 delete [] array;
二維數組(n行m列)利用new來進行動態分配、初始化及撤銷
//動態分配分塊連續內存及初始化 int **array; array=new int *[10]; for(int i=0;i<10;i++) { array[i]=new int [5]; memset(array[i],0,5*sizeof(int)); } //撤銷 for (int i = 0; i < 10; i ++) { delete[] array[i]; array[i] = NULL;//不要忘記,釋放空間后p[i]不會自動指向NULL值,還將守在原處,只是釋放內存而已,僅此而已。 } delete [] array; array=NULL;
補充一個不常用的分配方式:
int (*p)[4] = new int[3][4];
解釋:非動態分配,它的分配必須得有最外層 const 的支持
int x = 3, y = 4; int (*p)[y] = new int[x][y];//error,y必須是const,也就是不能動態。
所以這種方式不能達到真正的動態分配二維數組的目的,只能相當於半自動化的一個分配方式。
最后提醒:千萬不要有
int *p = new int[4][2];
這樣的錯誤寫法。
參考資料:
https://blog.csdn.net/diaodi1938/article/details/101491501