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

作者: TobyH4cker (Toby (我要當好人))   2015-05-13 03:15:38
※ 引述《Hazukashiine (恥ずかしい ね...(>///<))》之銘言:
: 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 的,它被編譯器巧妙地包裝了。
不用爭論了,反正下面三件事情結果都是一樣的:
#include <stdio.h>
int main()
{
int a[5];
printf("&a[0]\t%p\n", &a[0]);
printf("a\t%p\n", a);
printf("&a\t%p\n", &a);
return 0;
}
執行結果:
&a[0] 0018FF48
a 0018FF48
&a 0018FF48
反組譯奉上:
.text:004011E8 push ebp
.text:004011E9 mov ebp, esp
.text:004011EB add esp, 0FFFFFFECh
.text:004011EE lea eax, [ebp-14h] ; 是這樣
.text:004011F1 push eax ; &a[0]
.text:004011F2 push offset aA0P ; "&a[0]\t%p\n"
.text:004011F7 call 00403DA8 ; 前往 printf
.text:004011FC add esp, 8
.text:004011FF lea edx, [ebp-14h] ; 一樣
.text:00401202 push edx ; a
.text:00401203 push offset aAP ; "a\t%p\n"
.text:00401208 call 00403DA8 ; 前往 printf
.text:0040120D add esp, 8
.text:00401210 lea ecx, [ebp-14h] ; 還是一樣
.text:00401213 push ecx ; &a
.text:00401214 push offset aAP_0 ; "&a\t%p\n"
.text:00401219 call 00403DA8 ; 前往 printf
.text:0040121E add esp, 8
.text:00401221 xor eax, eax
.text:00401223 mov esp, ebp
.text:00401225 pop ebp
.text:00401226 retn
由於 a is an array of 5 int,
又 sizeof(int) = 4,
故 sizeof(a) = 5 * 4 = 20 跟ASM中的[ebp-0x14]符合,
add esp, 0FFFFFFECh 又 相當於 sub esp, 0x14
反正這個 array 會放在 stack,
會擔心找不到位址嗎?
編譯器都安排好一切了,
結案。
題外話我後來用MSVC CL沒有其他參數下編譯後,
&a[0]的部分反組譯結果是
.text:00401010 mov eax, 4 ; sizeof(int) = 4
.text:00401015 imul ecx, eax, 0 ; 0 elements
.text:00401018 lea edx, [ebp+ecx-18h]
有趣的是這樣比較貼近原始的意義,
是透過陣列元素型態的大小(4)和數量(0)來算所需的偏移量(ecx)。
作者: Feis (永遠睡不著 @@)   2015-05-13 07:55:00
array 不一定會放在 stack, 其實用組語解釋真的有點風險阿為甚麼人家 python 都不需要用組語 xD
作者: dritchie (卍~邁斯納效應~卍)   2015-05-13 08:11:00
樓上????
作者: TobyH4cker (Toby (我要當好人))   2015-05-13 09:49:00
是的我是以原發問者的例子來解釋而已C的好玩之處就是可以直接想像在CPU會怎麼運算
作者: Killercat (殺人貓™)   2015-05-13 11:20:00
用組語解釋其實是「編譯器」怎麼算 XD不過這個求證方法至少有90分 讚
作者: wenyonba (射後不理很XX啊!!!!)   2015-05-13 13:33:00
其實每次有這個問題的討論串,我都很想問,int a[5];到底什麼時候會用到 &a?? ?_?
作者: MOONRAKER (㊣牛鶴鰻毛人)   2015-05-13 14:06:00
不小心戳到的時候?
作者: bibo9901 (function(){})()   2015-05-13 14:15:00
通常就是用二維陣列的時候
作者: Killercat (殺人貓™)   2015-05-13 14:18:00
大概只有「特別指出避免被誤以為a是int的時候」吧
作者: TobyH4cker (Toby (我要當好人))   2015-05-13 14:49:00
可是用array本來就要有只有a時是什麼意義的觀念
作者: Feis (永遠睡不著 @@)   2015-05-13 15:03:00
wenyonba: 當你有個指標的陣列, 每個元素想指向陣列時傳統的例子就是一堆字串要排序.實際上應該還是有很多特殊的情境需要.陣列原則上也是 object 的一種, 這部分好像也沒道理要不一樣

Links booklink

Contact Us: admin [ a t ] ucptt.com