1. 程式人生 > >第二次考核問題總結

第二次考核問題總結

上題:int a[][3] = { {1, 2}, {3, 4, 5}, {6, 7, 8}, {9} };問:a[0][2]、a[0][3]、a[1][3]、a[0][8]、a[1][7]的值。

答案:0、3、6、8、0

解析:

首先說a[][3]的意思,後面的3表示數組裡最多儲存3個數。

a[0][2],0表示是第1個大括號({}),2表示第1個大括號({})裡的第3個值。顯然,沒越界(第1個數組的界),然後第3個值沒賦值,同時前兩個值賦值了,所以,第1個數組(大括號({}))的第3個值為0。

a[0][3],0還是表示第1個大括號,3表示第1個大括號裡的第4個值,越界了(最多隻能儲存3個值),越界後,就會跑到下一個陣列(大括號)裡,越了1個,所以,a[0][3]的值就為a[1][0]的值,即3。

a[1][3],1表示第2個大括號,3表示第2個大括號裡的第4個值,一樣,越界了,所以a[1][3]表示的就是a[2][0]的值,即6。

a[0][8],表示的是第1個大括號的第9個值,前面的值為(1,2,0;3,4,5;6,7),所以第9個值為8,即a[2][3]的值。

a[1][7],表示的是第2個大括號裡的第8個值,前面的值為(3,4,5;6,7,8;9),所以第8個值為0,即a[3][1]的值。

所以,可以再總結下:比如二維陣列,將其每個項的的最大的數值寫出來,像上面那個例子,每個項最大就為a[3][2],前面的項,第一個項,不能越界,第二個項裡的,可以越界,越出去的,就又從下一組裡的頭開始數,最後到了哪個數,就是哪個數。當然,如果把整個陣列的值都越完了也是不可以的。

對於陣列的整體賦值,只能在首次定義時整體賦值。解釋:定義陣列時,陣列的地址已經確定,並且不可修改,所以,如果在定義完陣列後,再整體(比如字串)賦值給陣列,就是要改變陣列的地址,這是不允許的。所以,要整體賦值,就儘快,要是等到已經定義完了,就不能再賦值了,因為陣列的地址已經確定,就不可再修改了。

例:char arr[20] = "helloworld";  正確!     char arr[20]; arr = "helloworld"; 錯誤!

        char arr[20] = "helloworld"; *(arr+1) = 'w';   正確!

但對於指標的整體賦值,可以任意時候賦值。解釋:定義指標,只是定義了一個位元組(32位)儲存指標的值,並且,它的值是可以被修改的,指標可以指向任意區域(或字串)。但,指標相對於陣列有個限制,即不能通過指標解引用修改相應記憶體區域的值,(此原因不確定:一個記憶體區域可以被多個指標所指向,這個記憶體是共享的,所以不能某個指標去修改它)

例:char *p = "helloworld";   正確!       char *p; p = "helloworld"; 正確!

       char *p = "helloworld"; *(p+1) = 'w';    錯誤!

int main()
{
	int a;
	int b[2];

	printf("%x,%x,%x\n", &a, &b[0], &b[1]);

	return 0;
}

如上,最後列印的值為什麼。

在vs2012中,答案肯定不唯一,記憶體地址是會變的,每次執行,它的地址都不一樣。但規律不會變。

首先,a、b[0]、b[1]都是在函式中的變數,區域性變數。所以,他們都位於棧中,所以,前面的變數位於後面變數的“下邊”(即高地址),對於棧而言,a是一個整體,b這個陣列是一個整體,所以,肯定a在b陣列的“下邊”,所以a的地址高,b陣列的地址低,理論情況,a的地址比b陣列的地址高sizeof(int)個位元組,即4個位元組,但在vs2012中,棧中的變數跟變數之間都會安防“兩個炸彈”,每個“炸彈”4個位元組,安全考慮(全域性變數區和動態記憶體區沒有“炸彈”)。所以,a的地址就會比陣列b的地址高4+4*2個位元組,即12個位元組。然後看b[0]和b[1],他倆位於一個數組中,陣列中的元素是按順序分配地址的,對於棧而言,b[0]和b[1]是一個東西,所以,b[0]和b[1]不遵循棧的規則,所以b[1]比b[0]大4個位元組。所以,結果肯定遵循這樣的規律:&b[0] + 4 = &b[1],&b[1] + 12 = &a。

未完待續......