2011-09-08 88 views
12

如果我存儲一個指向函數的指針,然後在我的程序執行期間的某個時間點,將它與同一函數的地址進行比較,兩個地址是否保證相等。C函數是否保證有固定的內存地址?

E.g.

int foo(void){return 0;} 
int (*foo_p)(void) = &foo; 

assert(foo_p == &foo); 

在上面的代碼中,斷言總是保證成功嗎?是否有任何的情況下函數的地址可以改變?

回答

17

每6.5.9:

兩個指針比較相等當且僅當兩者都是空指針,兩者都指向同一對象(包括一個指向對象和子對象在其開始)或函數,它們都是指向同一個數組對象的最後一個元素之後的指針,或者是指向一個指向一個數組對象末尾的指針,另一個指向不同數組對象開始的指針碰巧緊跟着地址空間中的第一個數組對象。

(黑體字爲補充強調。)

0

函數的地址,永遠不會改變。許多程序都是圍繞回調的概念構建的,如果函數的地址可能發生變化,則這些程序將不起作用。

如果假設函數的位置發生了變化,例如通過自修改程序,則對該函數的所有調用都會導致段錯誤或非常不確定的行爲。編輯:澄清 - 函數符號就像指針一樣,如果指針指向的內存不會將實際的指針變量歸零,它仍會指向那裏,就像函數調用仍然指向舊的被移動的位置一樣功能。

雖然自修改程序是非常大的例外,但在這些日子裏,二進制的代碼段是寫保護的,非常非常困難。