二維數組
二維數組本質上是以數組作為數組元素的數組,即“數組的數組”。
定義
類型說明符 數組名[常量表達式][常量表達式]
例如:
float a[3][4],b[5][10];
二維數組元素地址
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
int a[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int * p ;
// p=a ; 錯誤
p =a[0]; // ok
for(int i=0;i<12;i++)
cout<<*(p+i)<<"--------"<<p+i<<endl;
cout<<a<<endl; // a 與a[0]地址是一樣的.
cout<<a[0]<<endl;
return 0;
}
可以看出二維數組的內存地址是連續的。
因此,在棧區是占有一塊連續的內存。
#include <iostream>
using namespace std;
int main()
{
int a[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int * p ;
// p=a ; 錯誤
p =a[0]; // ok
for(int i=0;i<12;i++)
cout<<*(p+i)<<"--------"<<p+i<<endl;
cout<<"-----------------------"<<endl;
cout<<"a = "<<a<<endl; // 發現 a與a[0]地址是一樣的 : 0012FF50
cout<<"a[0] = "<<a[0]<<endl;
cout<<"*a = "<<*a<<endl;
// 下面3條原以為是輸出的元素的數值,結果 *a還個地址,且與a一樣的值
// 可見二維數組的名 是個 二級指針, a 是地址的地址
cout<<"-----------------------"<<endl;
cout<<"(*a) = "<<(*a)<<endl; // 對應元素1的地址 0012FF50
cout<<"(*(a+1)) = "<<(*(a+1))<<endl; // 對應元素5的地址 0012FF60
cout<<"(*(a+2)) = "<<(*(a+2))<<endl; // 對應元素9的地址 0012FF70
cout<<"-----------------------"<<endl;
cout<<"*(*a) = "<<*(*a)<<endl; //1
cout<<"*(*(a+1)) = "<<*(*(a+1))<<endl; //5
cout<<"*(*(a+2)) = "<<*(*(a+2))<<endl; //9
cout<<"-----------------------"<<endl;
cout<<"a[0] = "<<a[0]<<endl; // 對應元素1的地址 0012FF50
cout<<"a[1] = "<<a[1]<<endl; // 對應元素5的地址 0012FF60
cout<<"a[2] = "<<a[2]<<endl; // 對應元素7的地址 0012FF70
return 0;
}
/***********************************************************/
片段:
int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
int *p;
p=a; //? a是這個二維數組的首地址,但為什麼p=a就不行?
cout<<a<<"\n";
cout<<p<<endl;
直接“cout<<a”可以看到地址 就是a[0][0]
可是為什麼p=a就不行呢?a不是二維數組首地址嗎?為什麼非要用p=a[0]?
請教!
Ans ----------->
數據類型不同
p是指向int的指針
a可以看成指向int [3]的指針
int 和 int [3]不是同樣的類型,
前者是簡單數據類型,後者是由簡單數據類型構成的數組類型.
正因為這兩種數據的類型不同,所以指向它們的指針的類型也不同.
指針運算是按照指針的類型進行的,
所以p++只使p移動一個整數所占的字節長度,
a++卻移動了三個整數所占的字節長度,
由指針運算就可以看出這兩個指針不是同類型的.
不過指針間的強制轉換一般都還可行,
因而可以如下:
p=(int*)a;
雖然 a 和 a[0] 的類型不同,但它們的值是一樣的.
但值一樣卻未必是同樣的數據類型!
Ans ----------->
在除了sizeof、&和字符串常量之外的表達式中,array type會被自動轉換為pointer type。
對於p=a;這一句,a的類型是array type,就是int[3][3],a在賦予p之前,其類型先被自動轉換為pointer type,就是int(*)[3],轉換的結果是指向數組的指針,而p的類型是int*,是指向整數的指針,兩者類型不相容,不能直接賦值。
a[0]的類型也是array type,就是int[3],
同樣地,在表達式p=a[0]中a[0]也會先被自動轉換為pointer type,
就是int*,跟p的類型相容,因此可以p=a[0]。
Ans ----------->
解釋如下:
例如
int a[2][4]是一個二維數組,包含8個元素
這個數組表示為什麼呢:
表示為a數組有兩個元素(可以想象成一個結構,由4個int組成)
a就是這個數組的指針,指到a這個二維數組的第一個元素,即a[0](4個int組成的)
當你賦值的時候,編譯器認為a是一個4元素的結構,而p是一個int指針,類型不匹配,因此錯誤.
而a[0]則是a[0][0]的地址,a[0]的類型是int *,與p匹配,因此可以.
/***********************************************************/
舉例:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void main()
{
int i = 0, j = 0;
char buf[30];
char myArray[10][30] = {"ccccc", "aaaa", "bbbb","11111"};
//打印第二種內存模型
for (i=0; i<4; i++)
{
printf("%s \n", myArray[i]);
}
//排序
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (strcmp(myArray[i], myArray[j]) > 0)
{
strcpy(buf, myArray[i]);
strcpy(myArray[i],myArray[j]);
strcpy(myArray[j], buf);
}
}
}
//打印第二種內存模型
for (i=0; i<4; i++)
{
printf("%s \n", myArray[i]);
}
system("pause");
}
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//int array[10]===>int *array===>
// int printfArr22(char array[10], int iNum);
int printfArr23(char myArray[10][30], int iNum)
{
int i = 0;
for (i=0; i<iNum; i++)
{
printf("%s \n", myArray[i]);
}
return 0;
}
// int printfArr22(char array[10], int iNum);
int sortArr23(char myArray[10][30], int iNum)
{
int i = 0, j = 0;
char buf[30]; //buf數組名代表數組首元素的地址
//排序
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (strcmp(myArray[i], myArray[j]) > 0)
{
strcpy(buf, myArray[i]);
strcpy(myArray[i],myArray[j]);
strcpy(myArray[j], buf);
}
}
}
}
void main()
{
int i = 0;
char myArray[10][30] = {"ccccc", "aaaa", "bbbb","11111"}; //myArray數組名代表什麼?拋磚
//打印第二種內存模型
for (i=0; i<4; i++)
{
printf("%s \n", myArray[i]);
}
printf("第二種內存模型,排序之前\n");
printfArr23(myArray, 4);
//printfArr23(myArray[10][30], 4);
sortArr23(myArray, 4);
printf("第二種內存模型,排序之後\n");
printfArr23(myArray, 4);
system("pause");
}