2013-07-16 33 views
1

我想知道的數據類型使用變量名我可以從GCC中的變量名稱知道數據類型嗎?

我的最終目標是獲得一個函數簽名製作功能存根(框架代碼)

但GCC錯誤消息只通知唯一不確定的函數名

我可以看到符號表嗎? (對於推理函數簽名)

例如,foo.c的是像下面

#include <stdio.h> 

int main() { 
    int n = 0; 
    n = foo(); 
    return 0; 
} 

我想打一個函數存根

,所以我想知道函數foo沒有參數和返回整數值

我該怎麼辦?

我認爲如下:

  1. 接頭錯誤消息說函數foo是未定義

  2. 讀取線5

    N = FOO();

  3. 使用符號表

是不是檢查的n型?

對不起我的英文不好

教我推理的函數簽名

+0

但函數簽名與鏈接器錯誤無關 – perreal

+0

perreal謝謝,我知道這一點。所以我想看一個符號表......我該怎麼辦? – user1746360

+0

C符號表沒有任何類型信息。在內部,編譯器顯然需要構建和使用類型信息,但是這並不涉及目標文件。 – abarnert

回答

2

注入自己的代碼到源文件:

typedef struct { int a; char c; } badtype_t; 
badtype_t badtype; 

然後更換錯誤路線是這樣的:

n = badtype; //foo(); 

,或者如果你想要的類型foo回報:

badtype = foo(); 

那麼你會得到這樣的錯誤:

incompatible types when initializing type ‘int’ using type ‘badtype_t’ 

並且您可以獲得類型int

,或者如果你想的foo本身的類型:

foo * 2 

那麼你會得到一些錯誤,這樣的:

invalid operands to binary * (have 'int (*)()' and 'int') 

,你可以得到的類型int (*)()(即功能回吐沒有什麼,並返回一個int)。

+0

我想他試圖得到'foo'和/或'foo()'的類型,而不是'n'的類型(他已經在直接上面的行中)。 – abarnert

+0

@abarnert,很容易調整這個來獲得foo的類型。更新。 – perreal

+0

使用'clang',我得到了一個有用的答案:'錯誤:用不兼容的類型'int''表達式初始化'badtype_t'。但是對於gcc,無論是4.2還是4.8,我都會得到這個:'error:invalid initializer'。 – abarnert

0

似乎不錯,但這個策略是不夠好。使用表達式的左側不足以確定函數的返回類型。特別是,可能根本沒有左手邊,簡單地說:foo();。然後怎樣呢?

+0

我們的目標只是沒有編譯錯誤。所以我們不想要確切的返回類型。我如何推斷返回類型? – user1746360

+0

您可以將一個返回void的函數剔除,然後查看您將得到的未來錯誤類型。你可能會得到一些東西...... ..這個函數返回「void」並且不能被轉換爲「int」_ – CSJ

0

如果你只是想看到一個符號表,這就是nm的用途。

例如,如果你連接foo.obar.o在一起的錯誤,你可以這樣做:

nm -a foo.o 

會告訴你在模塊foo中定義的所有符號。

但我不明白爲什麼你認爲這會有所幫助。 C符號沒有任何類型信息。可能有足夠的元數據來區分外部鏈接,和/或分辨符號是否功能或數據,但就是這樣。無法從float告知int,或者從char *函數返回並返回不同char *的函數取兩個int並返回double

+0

嗯......好的,謝謝你的回答!然後我如何推理一個函數簽名? – user1746360

+0

從技術上講,你不能。實際上,您可以通過向編譯器尋求幫助來做到這一點。 – abarnert

0

所以,你有一些函數foo定義某處,你想知道它的類型是什麼。

如果你實際上並沒有爲foo#include d頭文件的某處的原型,這是很容易:

  • 如果你使用的C99,你的代碼是無效的。
  • 否則,foo必須不帶參數並返回int,否則您的代碼無效。

而這不是那些「技術上無效,但它適用於每個平臺」的情況;它休息。例如,用gcc 4.2 64位x86 Linux或Mac,如果你這樣做:

double foo(double f) { return f*2; } 

然後,沒有一個頭文件,這樣稱呼它:

double f = foo(2.0); 
printf("%f\n", f); 

如果編譯爲C89 ,這將編譯和鏈接就好了(鏗鏘聲或gcc 4.8會給你一個警告; gcc 4.2甚至不會默認這樣做),然後運行並打印出2.0。至少在x86_64上;在ARM7上,你會損壞堆棧,如果你幸運的話會出現段錯誤。 (當然,它實際上會增加一倍 - 無論是2.0還是一些隨機未初始化的值 - 但它不能將它返回給您;它將其保存在調用者不知道訪問的任意浮點寄存器中。)


如果在頭文件中,你可以隨時搜索。 emacs,圖形IDE等都非常擅長。但是你可以用兩種方式使用編譯器來幫助你。

首先,只是這樣做:

gcc -E main.c > main.i 
less main.i 

現在搜索/foo,你會發現它。

或者你可以欺騙編譯器給你一個錯誤消息,就像在perreal的答案中一樣。

相關問題