這可能是一個愚蠢的問題,但我正在讀一本書,他們向我飛濺了這段代碼
int arr[6][8];
int *ptr = &arr[0][0];
*(ptr 8) = 12; // arr[1][0]
printf("%d\n", arr[1][0]);
現在...我明白為什么這個指標指向那個單元格了,但是如果我必須使用 arr 識別符號,我應該用這種方式來代替
*(*(arr 1)) = 12; // arr[1][0]
但我不明白為什么我不能用另一種方式來代替
*(*(arr 8)) = 12;
也許我對指標和二維陣列的了解很差,但我真的很想了解這些東西是如何作業的。
預先感謝您的回答!
uj5u.com熱心網友回復:
一個陣列,無論是一維、二維還是更多,都不指向任何東西。它是連續記憶體中的一組相同型別的物件。
之后int arr[6][8];,arr是一個由 6 個 8 組成的陣列int。如果每個都int使用四個位元組,那么整個陣列在記憶體中使用 6?8?4 = 192 個位元組,sizeof arr計算結果為 192,因為arr 是陣列,并sizeof給出其運算元的大小。
當您arr在運算式中使用時,它將自動轉換為指向其第一個元素的指標,除非它是sizeofunary的或的運算元&。1因為arr是陣列陣列,所以它的第一個元素也是陣列。arris的第一個元素是arr[0]8 的陣列int。所以,在arr 1,arr被轉換成一個指標到它的第一個元素。該指標是&arr[0]的地址arr[0]。
當一個整數,比如n被添加到一個指標上時,結果指向陣列中另外n 個長元素。因此,當我們將 加 1 時&arr[0],我們得到&arr[1]。因此, in arr 1、arr自動轉換為&arr[0]、產生&arr[0] 1,然后加法產生&arr[1]。
因此,arr 1is &arr[1],這也是 where 的地方arr[1][0]。(注意 while&arr[1]和&arr[1][0]指向記憶體中的同一個地方,它們有不同的型別,所以編譯器在對它們進行算術運算時會以不同的方式對待它們。)
之后int *ptr = &arr[0][0];,ptr當然指向了arr[0][0]。然后ptr 8指向arr[0][8]如果有這樣的元素會在哪里。當然,沒有,因為arr[0]只有從arr[0][0]到的元素arr[0][7]。ptr 8分高出一分arr[0][7]。
指標演算法是由 C 標準定義的;您可以指向“超出最后一個元素的一個”。然而,這只是一個占位符指標,用于算術和比較。當您使用 取消參考指標時,C 標準不會發生*(ptr 8)。
我們知道那arr[1][0]是在arr[0][8]假設的地方。然而,C 標準并沒有給我們規定說我們絕對可以*(ptr 8)用來訪問arr[1][0]. 因此該代碼沒有 C 標準定義的行為。但是,許多編譯器會將其視為具有訪問arr[1][0]權限。
正如您所注意到的,*(*(arr 1))可用于訪問arr[1][0]. 它的作業方式是:
arr自動轉換為&arr[0].- 加 1 給出
&arr[1]. *取消參考&arr[1],產生arr[1].arr[1]是一個陣列,因此它會自動轉換為指向其第一個元素的指標。這產生&arr[1][0].*取消參考&arr[1][0],產生arr[1][0].
相反,*(*(arr 8))無法訪問arr[1][0]:
arr自動轉換為&arr[0].- 添加 8 給出
&arr[8].
現在我們已經遠遠超出了arr終點。arr只有從arr[0]to 的元素arr[5],所以arr[8]超出了 end 。
請注意,添加 8 以&arr[0]將指標移動陣列的8 個元素arr,而不是陣列的8 個元素arr[0]。也就是說,它將它移動了 8 個 8 陣列int,而不是 8 int。這是因為型別的&arr[0]是“指標的8陣列int”,而不是“指標int”。
當您將 8 添加到“指向”的指標時int,您將其移動 8 int。當您將 8 添加到“指向 8 陣列的指標int”時,您將其移動了 8 個 8 陣列int。
腳注
1所有陣列都是這樣自動轉換的,字串文字還有一個例外。當字串文字(字符陣列)用于初始化字符陣列時,它不會自動轉換為指標。
uj5u.com熱心網友回復:
*(*(arr 8)) = 12;
翻譯成
arr[8][0] = 12;
這是陣列邊界之外。在陣列邊界外寫入的行為是未定義的 - 它可能會立即崩潰,可能會破壞堆疊中的資料,或者可能在沒有任何明顯問題的情況下正常作業。
請記住,除非它是sizeof或 一元運算&符的運算元,否則“N 元素陣列”型別的運算式將T轉換或“衰減”為“指向T”型別的運算式,并且運算式的值是地址陣列的第一個元素。該運算式的arr型別為“ 的 8 元素陣列的 6 元素陣列int;在大多數情況下,它“衰減”為“指向 8 元素陣列的指標int”,或int (*)[8]。
將一個指標值加 1 會產生一個指向所指向型別的下一個物件的指標。如果運算式arr產生指向 的 8 元素陣列的指標int,則運算式arr 1產生指向緊隨其后的下一個8 元素陣列的int指標。因此
int int * int (*)[8]
–––
| | arr[0][0] p arr
–––
| | arr[0][1] p 1
–––
| | arr[0][2] p 2
–—–
...
–—–
| | arr[0][6] p 6
–––
| | arr[0][7] p 7
–––
| | arr[1][0] p 8 arr 1
—––
這就是為什么*(*(arr 8)) == arr[8][0]-arr 8產生一個指標的第8'8個元素的陣列int以下arr。這就是為什么*(*(arr 1)) == arr[1][0]。
uj5u.com熱心網友回復:
如果你只定義指標然后賦值,事情可能會更清楚:
int array[2][3] = {0, 1, 2, 3, 4, 5}; // array declared & initialized
int *ptr; // pointer is declared but not initialized (is not assigned a value)
// above, pointer "ptr" points to some random memory address
ptr = &array[0][0]; // pointer is assigned to point to the starting element of the array
ptr = array; // same as above; pointer is assigned to point to the starting element of the array
// "ptr" is the address of the memory the pointer points to
// "*ptr" is the integer value stored in the memory address the pointer points to
// if the array is declared as "array[m][n]", then;
// "*(ptr (i * n) j)" is equivalent to "array[i][j]" i.e. the value
// "(ptr (i * n) j)" is equivalent to "&array[i][j]" i.e. the memory address
@John Bollinger 說的有道理!事實上他是對的。C 中的陣列名稱不是我們期望的指標。下面的代碼解釋:
// array declared below on stack
int a[3] = {1, 2, 3};
// same array with same values stored on heap
int *b = malloc(3 * sizeof(int));
*(b 0) = 1;
*(b 1) = 2;
*(b 2) = 3;
printf("starting address of array a is %p\n", a);
printf("when treated like a pointer %p\n", &a);
printf("see, they are same!!!\n");
printf("\n");
printf("starting address of array b is %p\n", b);
printf("memory address of the pointer %p\n", &b);
printf("see, they are different!!!\n");
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/314983.html
