Re: [問題] 對陣列名稱取址
看板C_and_CPP作者Hazukashiine (恥ずかしい ね...(>///<))時間9年前 (2015/05/12 21:42)推噓5(5推 0噓 37→)留言42則, 5人參與討論串2/5 (看更多)
※ 引述《lalaboom (lalaboom)》之銘言:
: 標題: [問題] 對陣列名稱取址
: 時間: Tue May 12 19:54:31 2015
:
: 之前我的認知陣列名稱是一個常數指標,非指標常數喔,
:
: 1. 請問這個敘述對嗎?
:
: 現在有陣列 int b[2]; int a[2][3];
:
: 2. 請問為什麼 b 跟 &b 兩個address會一樣呢?
: 我可以理解 a, a[0], &a[0][0] 這3個一樣,
: 但是type不同,還是說這個認知也是錯的XD
:
: 3. 陣列在記憶體裏面除了宣告出來的連續空間,
: 陣列名稱是否會有另外像宣告指標一樣有一個變數空間嗎?
:
: 關於2之前好像有看到說&b = b 是定義好的 (compiler ? )
這些問題好像有許多的初學者都很困惑,
雖然明天我要考可怕的偏微分段考已經自顧不暇了,不過還是想回答一下。(笑
站在C語言本身的角度,陣列本身不是一個指標,它就是一個單單純純的陣列。
站在機器的角度,陣列佔據了記憶體一段連續的空閒,並且有個變數記錄了它的位置。
但是這個變數不是程式設計師可以直接獲得的,它需要進行轉換才能獲得。
先說說第二個好了:
b 跟 &b 的地址不一樣,簡單地說, &b 的地址並不存在,而且對編譯器來說是非法的。
因為當你在寫單獨一個 b 的時候, b 已經被隱式轉換成指標型態,而且這是被強制的。
在且 b 是一個右值(r-value),意思是你不能對此作取址的動作。
根據 ISO 文件 §4.2.1 Standard Conversions: Array-to-pointer conversion
An lvalue or rvalue of type "array of N T" or "array of unknown bound of T"
can be converted to an rvalue of type "pointer to T." The result is a pointer
to the first element of the array.
接下來的第三個也是一樣,
陣列名稱有佔空間嗎?結果呼之欲出,當然不佔。因為陣列名稱(b)是右值,並不佔空間。
可是你一定會很好奇不佔空間的話你的程式要如何知道陣列在哪?
這件事很妙,站在C語言的角度並不佔空間,但是實作上辦不到,所以當然要佔空間。
只是這個變數不是你的程式可以 access 的,它被編譯器巧妙地包裝了。
這樣很矛盾嗎?
其實,不。
因為程式語言本身定義的是語法結構,並不是實作的內容。
因此一個程式語言可以有很多種編譯器,像是 GCC C Compiler, MSVC etc.
如有錯誤歡迎指正。
( ̄▽ ̄#)=﹏﹏ 飄走=
--
當教授在講臺上C++的時候,我的臉比佳佳還要沮喪...
講正經的... C++是一個被過度設計的程式語言,完全遭透了!
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.113.91.124
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1431438143.A.864.html
※ 編輯: Hazukashiine (140.113.91.124), 05/12/2015 21:49:51
→
05/12 21:54, , 1F
05/12 21:54, 1F
&b 當然存在且合法。不存在的是 &b 的地址。
請您再仔細地看上文「&b 的地址(即&&b)並不存在,而且對編譯器來說是非法」
根據 ISO/IEC 9899:TC3 Committee Draft — Septermber 7, 2007 WG14/N1256
§6.5.3.4
3. ... When applied to an operand that has array type,
the result is the total number of bytes in the array.
這項目特別被舉出來是為了避免 sizeof(b) 中的 b 被 implicitly convert.
所以說,sizeof(b) 仍然是 int b[2] 這個陣列的位元組大小。
→
05/12 22:43, , 2F
05/12 22:43, 2F
b 是陣列名稱, b[] 才是是陣列,該陣列的型態是 int[2]。
b 不佔空間,只有 b[] 佔空間,但是實作上需要使用一個空間來儲存 b[2] 的地址。
而且這個空間也一樣是放在 stack 中,會隨函式的增長或消滅來生成與毀滅。
推
05/12 22:53, , 3F
05/12 22:53, 3F
推
05/12 22:57, , 4F
05/12 22:57, 4F
已修正,感謝提出錯誤。
→
05/12 22:58, , 5F
05/12 22:58, 5F
這是邏輯謬誤,使用C++來檢視C?
在C語言中,不實際擁有在記憶體中一塊物理位置的稱之為右值。
b 是陣列名稱(並非陣列本身),當然在記憶體中不擁有物理位置。
推
05/12 22:58, , 6F
05/12 22:58, 6F
→
05/12 22:58, , 7F
05/12 22:58, 7F
→
05/12 23:15, , 8F
05/12 23:15, 8F
推
05/12 23:15, , 9F
05/12 23:15, 9F
不然大大覺得應該要如何準確地表示陣列?
陣列一語本來就不是正確的語法,最正確的用法是:
It has type `int[2]`.
推
05/12 23:17, , 10F
05/12 23:17, 10F
L-values have storage addresses that are programmatically accessible to the
running program, meaning that they are variables or dereferenced references to
a certain memory location.
Does b have its own storage address? Only b[0] and b[1] does!
→
05/12 23:21, , 11F
05/12 23:21, 11F
→
05/12 23:22, , 12F
05/12 23:22, 12F
→
05/12 23:24, , 13F
05/12 23:24, 13F
`b` has type `int[2]`, and `&b` has type `int(*)[2]`.
Type `int(*)[2]` will decay to `int*` while the array length is useless.
→
05/12 23:26, , 14F
05/12 23:26, 14F
→
05/12 23:27, , 15F
05/12 23:27, 15F
→
05/12 23:27, , 16F
05/12 23:27, 16F
我承認我真的不知道 b 是不是 array type,
但是 b 肯定是 int[2],只是在程式碼中會被轉型成 int(*)[2]。
→
05/12 23:41, , 17F
05/12 23:41, 17F
絕不是 int*
http://stackoverflow.com/questions/2893911/
address-of-an-array-address-of-being-ignored-be-gcc
int(*)[2] 會 decay 成 int* 當陣列長度無用的時候,
→
05/12 23:45, , 18F
05/12 23:45, 18F
→
05/12 23:46, , 19F
05/12 23:46, 19F
A pointer that points to an array of 50 ints has type int (*)[50] - that's
the type of &test.
→
05/12 23:48, , 20F
05/12 23:48, 20F
是呀~所以 &b has type `int(*)[2]` not type `int*`.
→
05/12 23:49, , 21F
05/12 23:49, 21F
→
05/12 23:50, , 22F
05/12 23:50, 22F
喔喔喔~我錯亂惹~
整理一下:
b: int[2] -> int* (implicit conversion: array-to-pointer conversion)
&b: int(*)[2] (address-of operator)
→
05/12 23:57, , 23F
05/12 23:57, 23F
→
05/12 23:58, , 24F
05/12 23:58, 24F
搞不好真的不是,中文有時候會怪怪der.
→
05/13 00:00, , 25F
05/13 00:00, 25F
XDDD
錯亂惹啦~先去準備偏微分啦!!!
這篇的重點是:
1. Implicit type conversion: array-to-pointer conversion
2. b has type int[2], and &b has type int(*)[], and &&b is invalid.
→
05/13 00:03, , 26F
05/13 00:03, 26F
暈~
b 在 code 中被轉換的才是 rvalue,
在 sizeof operator 中不用被轉換,是 lvalue!!!
→
05/13 00:06, , 27F
05/13 00:06, 27F
喔喔喔~是 Implicit type conversion
改了改了
→
05/13 00:10, , 28F
05/13 00:10, 28F
眼殘XD
compiler 很聰明吧~
也許看到前方有&就不會作 implicit conversion 吧?阿災?
→
05/13 00:11, , 29F
05/13 00:11, 29F
→
05/13 00:12, , 30F
05/13 00:12, 30F
→
05/13 00:14, , 31F
05/13 00:14, 31F
→
05/13 00:14, , 32F
05/13 00:14, 32F
我翻遍標準文檔就還是覺得怪怪的
可能就真的不隱式轉換了吧~
※ 編輯: Hazukashiine (140.113.91.124), 05/13/2015 00:18:09
→
05/13 00:25, , 33F
05/13 00:25, 33F
→
05/13 14:57, , 34F
05/13 14:57, 34F
→
05/13 14:57, , 35F
05/13 14:57, 35F
→
05/13 15:02, , 36F
05/13 15:02, 36F
→
05/13 15:02, , 37F
05/13 15:02, 37F
→
05/13 15:03, , 38F
05/13 15:03, 38F
→
05/13 17:09, , 39F
05/13 17:09, 39F
→
05/13 17:20, , 40F
05/13 17:20, 40F
→
05/13 17:57, , 41F
05/13 17:57, 41F
→
05/13 17:59, , 42F
05/13 17:59, 42F
討論串 (同標題文章)