![](/img/trans.png)
[英]Where does the standard define the order of preference for binding of values to references?
[英]Does the standard define the type for `a[i]` where `a` is `T [M][N]`?
我偶爾會使用多維數組,並且很好奇標准所說的(C11和/或C ++ 11)索引的行為,其“維度”小於為數組聲明的索引。
鑒於:
int a[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
標准是說a[1]
是什么類型,還是a[0][1]
,它是否合法,是否應該按預期正確地索引子數組?
auto& b = a[1];
std::cout << b[1][1];
m[1]
只是int[2][2]
。 同樣, m[0][1]
只是int[2]
。 是的,作為子數組的索引按照您的想法運行。
標准是否定義
a[i]
的類型,其中a
是T [M][N]
?
當然。 該標准基本上定義了所有表達式的類型,如果不是,則它將是缺陷報告。 但我想你對這種類型更感興趣......
雖然標准可能沒有明確提到你的情況,但規則是陳述的並且很簡單,給定類型為T
的N
元素的數組a
,表達式a[0]
是類型T
的左值表達式。 在變量聲明int a[2][2]
中, a
的類型是兩個類型為int
的兩個元素的數組元素的數組 ,它應用上面的規則意味着a[0]
是一個2元素數組的左值 ,或者你必須在程序中輸入它: int (&)[2]
。 添加額外的維度不會影響機制。
我認為C11中的這個例子含蓄地解釋了它。
C11 6.5.2.1數組下標
示例考慮由聲明
int x[3][5];
定義的數組對象int x[3][5];
這里x
是3×5的整數數組; 更確切地說,x
是一個由三個元素對象組成的數組,每個元素對象是一個由五個整數組成的數組。 在表達式x[i]
,它等價於(*((x) + (i)))
,x
首先被轉換為指向五個int的初始數組的指針。 然后根據x
的類型調整i
,這在概念上需要將i
乘以指針所指向的對象的大小,即五個int
對象的數組。 添加結果並應用間接以產生五個整數的數組。 當在表達式x[i][j]
,該數組又被轉換為指向第一個int的指針,因此x[i][j]
產生一個int
。
類似的是在C ++ 11 8.3.4數組中
示例:考慮
int x[3][5];
這里
x
是3×5的整數數組。 當x
出現在表達式中時,它將轉換為指向(三個中的第一個)五元數組整數的指針。 在表達式x[i]
,它等價於*(x + i)
,x
首先被轉換為如上所述的指針; 然后將x + i轉換為x
的類型,其涉及將i
乘以指針所指向的對象的長度,即五個整數對象。 添加結果並應用間接以產生一個數組(五個整數),然后將其轉換為指向第一個整數的指針。 如果有另一個下標,則同一參數再次適用; 這次結果是一個整數。 - 末端示例] - 尾注]
要記住的關鍵點是,在C和C ++中,多維數組只是一個數組數組(因此三維數組是數組數組的數組)。 多維數組的所有語法和語義都遵循它(當然還有語言的其他規則)。
所以給定一個對象定義:
int m[2][2][2];
m
是int[2][2][2]
類型的對象(兩個數組的數組,每個數組由兩個元素組成,每個元素由兩個元素組成,每個元素都是兩個int
的數組) 。
當你寫m[1][1][1]
,你已經在評估m
, m[1]
和m[1][1]
。
表達式m
是一個引用int[2][2][2]
類型的數組對象的左值。
在m[1]
,數組表達式m
被隱式轉換為(“衰減”)指向數組第一個元素的指針。 該指針的類型為int(*)[2][2]
,指向int
的雙元素數組的雙元素數組。 根據定義, m[1]
相當於*(m+1)
; +1
將m
前進一個元素並取消引用結果指針值。 因此m[1]
引用int[2][2]
類型的對象(兩個數組的數組,每個數組由兩個int
元素組成)。
(數組索引operator []
被定義為對指針而不是數組進行操作。在像arr[42]
這樣的常見情況下,指針恰好是隱式數組到指針轉換的結果。)
我們重復m[1][1]
,給我們一個指向兩個int
( int(*)[2]
類型int(*)[2]
數組的指針。
最后, m[1][1][1]
得到了評估m[1][1]
並再次重復該過程,給出了一個引用int
類型對象的左值。 這就是多維數組的工作原理。
只是添加到輕浮,像foo[index1][index2][index3]
這樣的表達式可以直接使用指針和數組。 這意味着您可以使用指針和任意大小的分配來構造一些(幾乎)像真正的多維數組一樣的東西。 這使您可以在每行中使用“不規則”數組,其中包含不同數量的元素,甚至是缺少的行和元素。 但是,由您來管理每一行的分配和釋放,甚至是每個元素。
推薦閱讀: comp.lang.c FAQ的第6部分。
旁注:有些語言中多維數組不是數組數組。 例如,在Ada中(使用括號而不是方括號進行數組索引),您可以擁有一個數組數組,索引類似於arr(i)(j)
,或者您可以擁有一個二維數組,索引類似於arr(i, j)
。 C不同; C沒有對多維數組的直接內置支持,但它為您提供了自己構建它們的工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.