Re: [問題] 對陣列名稱取址

看板C_and_CPP作者 (恥ずかしい ね...(>///<))時間9年前 (2015/05/12 21:42), 9年前編輯推噓5(5037)
留言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
&b 存在且合法. b 不佔空間的話, 試解釋 sizeof(b)
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
b 是個陣列. 但是不占空間嗎? 蠻有趣的
05/12 22:43, 2F
b 是陣列名稱, b[] 才是是陣列,該陣列的型態是 int[2]。 b 不佔空間,只有 b[] 佔空間,但是實作上需要使用一個空間來儲存 b[2] 的地址。 而且這個空間也一樣是放在 stack 中,會隨函式的增長或消滅來生成與毀滅。

05/12 22:53, , 3F
b 是 lvalue
05/12 22:53, 3F

05/12 22:57, , 4F
b[2]不是陣列, b[2]是陣列的第3個element
05/12 22:57, 4F
已修正,感謝提出錯誤。

05/12 22:58, , 5F
b 是 lvalue (這很重要) http://ideone.com/mKCvI2
05/12 22:58, 5F
這是邏輯謬誤,使用C++來檢視C? 在C語言中,不實際擁有在記憶體中一塊物理位置的稱之為右值。 b 是陣列名稱(並非陣列本身),當然在記憶體中不擁有物理位置。

05/12 22:58, , 6F
那你怎麼解釋An lvalue or rvalue of type "array of N
05/12 22:58, 6F

05/12 22:58, , 7F
T"這個東西?
05/12 22:58, 7F

05/12 23:15, , 8F
放在 stack 中? 這也蠻有趣的
05/12 23:15, 8F

05/12 23:15, , 9F
修正後仍是錯,b[]不是正確的語法,更別說他代表什麼了
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
對了. 忘了問 4.2.1 的那節是 ISO C 哪個版本?
05/12 23:21, 11F

05/12 23:22, , 12F
我建議你可以去 C 標準找一下 rvalue (如果你在說 C 的話)
05/12 23:22, 12F

05/12 23:24, , 13F
所以你的 compiler 印不出 &b ?
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
此外你可以想想 struct 變數~ 比對一下跟 array 的差別
05/12 23:26, 14F

05/12 23:27, , 15F
還有你的 sizeof 的說明不是已經說了 b 是 array type ?
05/12 23:27, 15F

05/12 23:27, , 16F
如果 b 不是 array type, 那 sizeof(b) 到底是甚麼.. 頭痛
05/12 23:27, 16F
我承認我真的不知道 b 是不是 array type, 但是 b 肯定是 int[2],只是在程式碼中會被轉型成 int(*)[2]。

05/12 23:41, , 17F
b 會被轉成 &b[0] 喔~ 所以是 int * 而不是 int(*)[2]
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
恩.. 我們看的是同一篇嗎 XDDDDD
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
是阿. 那不就是 &b 嗎 xD
05/12 23:48, 20F
是呀~所以 &b has type `int(*)[2]` not type `int*`.

05/12 23:49, , 21F
但是你說的不是 b 在程式碼中會被轉 int (*)[2] 嗎?
05/12 23:49, 21F

05/12 23:50, , 22F
我說的是 b 會轉為 int * 不是 &b 阿 QQ
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
用編輯文章好難回阿 xD 原文 &b 的 address 應該不是 &&b 的
05/12 23:57, 23F

05/12 23:58, , 24F
意思. 或者我以為他不是 xD
05/12 23:58, 24F
搞不好真的不是,中文有時候會怪怪der.

05/13 00:00, , 25F
你是跟葉孤紅一樣有人專門寫一本錯誤的書給你看嗎 XD
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
既然 b 是一個 rvalue 那你怎麼能用 address-of 呢?
05/13 00:03, 26F
暈~ b 在 code 中被轉換的才是 rvalue, 在 sizeof operator 中不用被轉換,是 lvalue!!!

05/13 00:06, , 27F
提醒一下... standard conversion 是 C++ 的...
05/13 00:06, 27F
喔喔喔~是 Implicit type conversion 改了改了

05/13 00:10, , 28F
我說的是 address-of "&" 不是 sizeof
05/13 00:10, 28F
眼殘XD compiler 很聰明吧~ 也許看到前方有&就不會作 implicit conversion 吧?阿災?

05/13 00:11, , 29F
如果 b 不佔空間的 rvalue, 那你寫下 &b 就是非法的
05/13 00:11, 29F

05/13 00:12, , 30F
其實我不知道 rvalue 不占空間這樣的說法到底該怎麼解釋 xD
05/13 00:12, 30F

05/13 00:14, , 31F
我是覺得 rvalue 很玄阿~ 大家晚安~
05/13 00:14, 31F

05/13 00:14, , 32F
的確很怪, 但暫且假設如他所說的那樣, 對 b 取址更怪
05/13 00:14, 32F
我翻遍標準文檔就還是覺得怪怪的 可能就真的不隱式轉換了吧~ ※ 編輯: Hazukashiine (140.113.91.124), 05/13/2015 00:18:09

05/13 00:25, , 33F
對轉換有興趣請參閱 C89 標準 3.2.2.1
05/13 00:25, 33F

05/13 14:57, , 34F
94行說 "使用C++來檢視C?"
05/13 14:57, 34F

05/13 14:57, , 35F
但 35行 "ISO 文件 §4.2.1" 似乎引自 C++ ??
05/13 14:57, 35F

05/13 15:02, , 36F
另外, 原原PO問 "為什麼 b 跟 &b 兩個address會一樣"
05/13 15:02, 36F

05/13 15:02, , 37F
然後 30行那邊回 "b 跟 &b 的地址不一樣" ...
05/13 15:02, 37F

05/13 15:03, , 38F
感覺答非所問? 還是 "地址不一樣" 似乎不是唯一解??
05/13 15:03, 38F

05/13 17:09, , 39F
上面 F大的 3.2.2.1 其實是指 6.3.2.1 ?
05/13 17:09, 39F

05/13 17:20, , 40F
yvb: 好像是版本差異 XD 那是 C89 Draft
05/13 17:20, 40F

05/13 17:57, , 41F
soga... C89 3.2.2.1 => C90 6.2.2.1 => C99~C11 6.3.2.1
05/13 17:57, 41F

05/13 17:59, , 42F
c89 要 google ansi.c.txt 才找得到 :P (好像沒 pdf 的?)
05/13 17:59, 42F
文章代碼(AID): #1LKWC_Xa (C_and_CPP)
文章代碼(AID): #1LKWC_Xa (C_and_CPP)