在討論這個問題前, 我們先看一段**。這段**,大家都會很容易看懂, 但是真正能夠明白的我不知道有幾。
/* ** 1-1 */
#include int main()
; int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
return 0;
}
輸出結果為: 2, 5
討論:
當我第一眼看到這個**的時候, 我的第一直覺答案是2, 1. 但是當執行結果出來以後, 我蒙了。為什麼會是2, 5 呢。後來我就測試了輸出他的位址(原來最終問題,通過檢視記憶體才是王道),我就發現了問題的所在。主要的原因就在於 &a + 1 這裡。這裡給出我檢視記憶體運**況的**:
/* **1-2 */
#include int main() ;
printf("c = %p, c+1 = %p, &c+1 = %p\n", c, c+1, &c+1);
/* 陣列名c 的位址, 陣列名c + 1 的位址, 陣列名位址 + 1 的位址*/
return 0;
}
執行結果: c = 0022ff18, c+1 = 0022ff1c, &c+1 = 0022ff30
通過這個輸出結果, 我們不難看出,c+1 的位址是在陣列位址(c 的位址)的基礎上加了1 個int。但是,&c + 1 的位址是在陣列位址(c 的位址)的基礎上加了6 個int 。而這6 個int 就是整個陣列的長度。這不是偶然,這是必然。就是說,在陣列位址的基礎上加 1 就相當於再加了乙個陣列(跳過乙個陣列的長度)。
這樣我們就不難解釋上面** 1-1,為什麼結果是2, 5 。
int *ptr=(int *)(&a+1);
這裡的ptr 位址實際上就是跳到整個陣列的最末端,然後新開始的乙個陣列(即元素5 後面的乙個位置)。所以,當輸出*(ptr-1) 就是5 。
討論了一維陣列的情況, 下面我們接著看看二維陣列。
按理說,把一維陣列弄明白了二維陣列就很簡單,這裡因為筆者在後面寫二維陣列的時候也遇到了點麻煩,所以就多多囉嗦一下。
下面我們看一段測試**:
/* ** 2 - 1 */
#include int main()
, };
// 陣列名的不同 +1
printf("結果1\n");
printf("** a = %d\n", **a);
printf("a = %p\n", a);
printf("&a = %p\n", &a);
printf("a+1 = %p\n", a+1);
printf("&a+1 = %p\n", &a+1);
printf("\n");
// 陣列起始單元的不同+1
printf("結果2\n");
printf("* a[0] = %d\n", *a[0]);
printf("&a[0] = %p\n", &a);
printf("a[0]+1 = %p\n", a[0]+1);
printf("&a[0]+1 = %p\n", a[0]+1);
printf("\n");
// 陣列中間單元不同+1
printf("結果3\n");
printf("a[0][1] = %d\n", a[0][1]);
printf("&a[0][1] = %p\n", &a[0][1]);
printf("&a[0][1]+1 = %p\n", &a[0][1]+1);
return 0;
}
輸出結果為:
結果1** a = 1
a = 0022ff18 // 陣列名
&a = 0022ff18 // 陣列名位址
a+1 = 0022ff24 // 陣列名加1 , 結果為跳轉到下一行(即第二行,這裡跳過3 個int)開頭。
&a+1 = 0022ff30 // 陣列名位址加1, 按照上文介紹,跳轉到下乙個陣列的位置(即跳過整個數 組,如果是加2 , 那麼就跳過2 個陣列空間的位置。),這裡就跨過了6 個int 的空間。
結果2* a[0] = 1
&a[0] = 0022ff18 // 陣列中第一行行名位址
a[0]+1 = 0022ff1c // 陣列中第一行行名加1, 結果為跳轉到同行的下乙個元素位置(跳過1 個int)
&a[0]+1 = 0022ff24 // 陣列中第一行行名位址加1, 結果為跳轉一行的位址,到下一行的行頭位置 (即跳轉了3 個int 位置)。
結果3a[0][1] = 2
&a[0][1] = 0022ff1c // 陣列中位置為[0][1] 的位址
&a[0][1]+1 = 0022ff20 // 陣列中位置為[0][1] 的位址加1 ,結果跳轉了1 個int 的位置。跳轉到同行的下一 個元素位置。是本行的行末位置,那麼就跳轉到下一行的開頭位置。
這段**有點多, 都是printf(); 這個不重要,重要的是輸出的內容。分析就在答案的後面注釋。
從這裡的結果, 我們可以看出結果3中的 &a[0][1]+1 = 0022ff20 與結果1, 結果2中的 &a+1 = 0022ff30 , &a[0]+1 = 0022ff24 運算方式是不同的。這是因為,結果1和結果2 中是對陣列名位址加1, 而結果3 不是 對陣列名位址加1, 他只是陣列中間的乙個元素位址。如果要進一步深究,我們可以再把指標帶進來考慮就可以更加清晰明白。
指標的操作,就相當於上面結果3 的操作結果一樣。他的操作都是按部就班,不會存在因為加1 而跳轉乙個陣列的長度的情況。下面我們看看測試**:
/* ** 3 -1 */
#include int main()
, };
int *p1 = *a; // 取a 的位址
int *p2 = a[0]; // 取a[0] 的位址
int *p3 = &a[0][1]; // 去a[0][1] 的位址
printf("p1 = %p \n", p1);
printf("p1+1 = %p \n", p1+1);
printf("p2 = %p \n", p2);
printf("p2+1 = %p \n", p2+1);
printf("p3 = %p \n", p3);
printf("p3+1 = %p \n", p3+1);
return 0;
}
輸出結果:
p1 = 0022ff0c
p1+1 = 0022ff10
p2 = 0022ff0c
p2+1 = 0022ff10
p3 = 0022ff10
p3+1 = 0022ff14
從這個結果可以看出指標的跳轉是按位置跳轉的。一次只能跳轉偏移個數個位置。
比如: int *p = a; p + 3; 就表示跳轉從當前p 的位置, 跳轉到之後的第三個位置。
總結:
綜上所訴,筆者最想表達的是,在陣列名取位址然後增加偏移量時, 他是按照整個陣列再進行跳轉。即跳過整個陣列的長度的偏移量倍。
Unity 產生各不相同的隨機數
1.網上很多方法都說用時間種子來解決,但是在極短的時間內,這種方法沒效 random r new random datetime.now.millisecond random counter new random unchecked int datetime.now.ticks ctr random...
oracle查詢多條條件各不相同的資料
object object employeeservice.querybysqluniqueresult select select count from pm overtime where empid employee.getid and overtype 3 and overdate to da...
Unity菜鳥 產生各不相同的隨機數
1.網上很多方法都說用時間種子來解決,但是在極短的時間內,這種方法沒效 random r new random datetime.now.millisecond random counter new random unchecked int datetime.now.ticks ctr random...