2012-04-10 170 views
5

我遇到了一些問題,我正在測試一個示例代碼,因爲我的abs函數沒有返回正確的結果。 ABS(-2)的outputing -2(這,順便說一句,是suposed是絕對值函數,如果不清楚)GCC函數名稱衝突

變得有點絕望後,我終於有了下面的代碼

#include <stdio.h> 

unsigned int abs(int x) { 
    return 1; 
} 

int main() { 
    printf("%d\n", abs(-2)); 
    return 0; 
} 

這沒有什麼用處,但它可以顯示我的問題。當輸出爲1時,輸出爲-2。

如果我將函數名更改爲其他值(例如abs2),結果現在是正確的。另外,如果我將它改爲接收兩個參數而不是一個,它也解決了這個問題。

我明顯的猜測:與標準abs函數的衝突。但是這仍然不能解釋爲什麼輸出是-2(如果使用標準abs函數,它應該是2)。我想檢查兩個版本的組件輸出(與函數命名ABS和ABS2)

這裏的diff的輸出兩個組裝件:

23,25c23,25 
< .globl abs 
< .type abs, @function 
< abs: 
--- 
> .globl abs2 
> .type abs2, @function 
> abs2: 
54c54 
< .size abs, .-abs 
--- 
> .size abs2, .-abs2 
71c71,74 
< movl -4(%rbp), %edx 
--- 
> movl -4(%rbp), %eax 
> movl %eax, %edi 
> call abs2 
> movl %eax, %edx 

據我所知,第一個版本(其中功能命名爲abs)簡單地放棄函數調用,因此使用參數x而不是abs(x)

所以總結一下:爲什麼會發生這種情況,特別是因爲我找不到任何警告或有關此錯誤。

測試Debian的擠壓,GGC 4.4.5,並且還對GCC 4.1.2

+0

這裏是ideone的一個例子http://ideone.com/YpnkE – 2012-04-10 11:22:07

回答

7

GCC是打在你的招數由於以下的相互作用:

  • abs是一個內置功能;
  • 您聲明abs返回unsigned int而標準(和內置)abs返回signed int

嘗試編譯gcc -fno-builtin;在我的盒子上,給出了預期的結果1。編譯沒有該選項,但abs宣佈爲返回signed int導致程序打印2

(真正解決這個問題是不爲自己的函數使用的庫標識。還要注意的是,你不應該與%d印刷unsigned int

+0

謝謝,這澄清了它的一部分。我知道內建函數,而我雖然像-fno-builtin可能會解決它,但我不知道實際的標誌名稱。儘管如此,當使用第二種解決方案(將函數聲明爲signed int)時,2的輸出意味着內置函數被調用而不是我的,這導致我的另一個問題:我不應該對此行爲發出警告嗎?在一個真正的大型項目中,這種問題可能會讓我們非常頭疼,以確認 – Naps62 2012-04-10 11:43:53

+0

@ Naps62:是的,一個警告會很好,但看起來GCC(甚至是「WALL -Wextra -pedantic」)只是不會給你一個。最好小心你的標識符。 – 2012-04-10 11:46:49

2

gcc優化呼叫abs()使用其內置abs()。因此,如果您使用​​選項(或將abs()定義爲返回int),您會注意到您會得到正確的結果。據this(引用):

GCC包括內置許多在 標準C庫函數的版本。如果指定-fno-builtin選項,則以_ 內置作爲前綴的版本始終會被視爲與C庫函數具有相同的含義,即使 也是如此。 (請參閱C語言選項)這些功能的許多 僅在某些情況下進行了優化; 如果它們是 未在特定情況下優化,則將調用庫函數 將發射

如果您包含stdlib.h,它首先聲明abs(),那麼在編譯時會出現錯誤。

+0

我發佈的程序不會像預期的那樣回退到內置函數。相反,它只是忽略了函數調用,將abs(-2)視爲-2。另外,我試過你的建議,包括stdlib.h,並沒有編譯時錯誤,問題依然存在 – Naps62 2012-04-10 11:53:50

+0

我發現很難相信,因爲你正在定義一個函數叫'abs()'與類型衝突'stdlib.h'。即使沒有任何嚴格或迂腐的選項,gcc 4.1.2和4.4.7都會發出編譯錯誤。 – 2012-04-10 12:05:10

2

聽起來很像this bug,這是從2007年開始,並被指出是固定的。

編譯時,您當然應該嘗試編譯時不使用GCC的內在函數,即通過​​(或只是-fno-builtin-abs來剔除只有abs())。