2010-10-14 145 views
1

我是C編程的新手,我無法理解編譯我的程序時出現的錯誤。我有下面的程序,這是相當簡單的,並且我的教授說是正確的:未定義變量錯誤

#include <stdio.h> 
#define TRUE 1 
#define FALSE 0 
#define BOOL int 

extern int x; 
extern BOOL do_exp; 
int exp_or_log(); 

main() 
{ 
    x = 10; 
    do_exp = TRUE; 
    printf("2^%d = %d\n", x, exp_or_log()); //should print 1024 

    x = 145; 
    do_exp = FALSE; 
    printf("log(%d) = %d\n", x, exp_or_log()); //should print 7 
} 

但是當我嘗試編譯它,我得到:

"_x", referenced from: 
     _x$non_lazy_ptr in ccWdLlxk.o 
    "_exp_or_log", referenced from: 
     _main in ccWdLlxk.o 
     _main in ccWdLlxk.o 
    "_do_exp", referenced from: 
     _do_exp$non_lazy_ptr in ccWdLlxk.o 
ld: symbol(s) not found 

我甚至不對於知道從哪裏開始嘗試找出問題的含義有足夠的瞭解。如果任何人有一個有用的解釋,甚至只是一個我應該看看什麼開始問題拍攝的一般概念,我真的很感激它。

+3

「x」,「do_exp」和「exp_or_log()」定義在哪裏? – 2010-10-14 19:06:47

+0

可以使用'boolean'代替'BOOL',並且可能爲'TRUE'和'FALSE'定義不需要。 – Arun 2010-10-14 20:00:59

+0

使用**全局變量**'do_exp'來控制函數'exp_or_log()'的行爲,可能是'exp()'和'log()',這很奇怪。 – Arun 2010-10-14 20:03:50

回答

1

這不是抱怨編譯器:

ld: symbol(s) not found 

鏈接器(LD)找不到引用的符號。你還沒有提供他們的定義。

1

您已經聲明編譯器,這些變量和函數都可以,但不一定在這個特定的源文件中定義:

extern int x; 
extern BOOL do_exp; 
int exp_or_log(); 

,他們不是在源文件中定義。但是,鏈接器需要能夠解析這些名稱,並且您收到的錯誤消息表明鏈接器無法在其任何輸入文件中找到這些名稱。

您需要枯萎提供連接器(ld)與具有這些東西,或者你需要定義它們C文件庫,並ahave是C文件也編譯和鏈接。

2

xdo_expexp_or_log()都在另一個文件中定義,我猜是由您的教授提供的。您需要將該文件鏈接在一起。這通常是通過在您的編譯行中添加文件名和您的文件名來完成的。

0

您遇到鏈接問題。

見你的代碼的頂部:

extern int x; 
extern BOOL do_exp; 
int exp_or_log(); 

這些三條線都像承諾的編譯器。你是說,相信我,到時候你可以找到一個整數x,一個BOOL do_exp和一個函數exp_or_log();

extern對變量和函數沒有body的事實做出了這個承諾:{...}使得它成爲函數。

鏈接器抱怨,因爲你沒有遵守你的承諾。您需要實現exp_or_log(),並聲明x和do_exp。

有更多的代碼?如果您創建另一個文件,則調用x.h,其中包含以下內容: int x; int do_exp; int exp_or_log(){ return 6; }

,然後包括這在你的.c文件:

#include "x.h" 

你會得到一些輸出。在這種情況下,它是無意義的,但它會在編譯時解決邏輯問題。

$ ./a.out 
2^10 = 6 
log(145) = 6 
1

首先,請注意您如何在兩個變量定義中使用extern關鍵字。

extern int x; 
extern BOOL do_exp; 

這意味着:

這些變量在其它地方 (的extern烯丙基)創建。您應該知道它們存在 ,但它們在其他地方存在 。

如果這些變量是有意在另一個文件中聲明的,則需要將其他文件與您的鏈接編譯並鏈接在一起。

但是,我懷疑你更可能只是想宣佈他們。

int x; 
BOOL do_exp; 

舉報此事,我們將開始處理您的功能exp_or_log

1

我猜您使用的是* nix的機器從輸出,所以你將需要:

cc -c Anna_program.c 

這將產生Anna_program.o。在你的錯誤中,亂碼.o文件與這個文件相同,但是是臨時的,所以被賦予了一個psudo隨機名稱。 -c標誌具有僅編譯源文件的效果,並且留下了用於稍後生成可執行文件的鏈接。

然後,你可以這樣做:

cc Anna_program.o other_file.o -o Anna_program 

,併產生可執行Anna_program。如果你沒有使用* nix風格的編譯器,那麼你的設置會有所不同,你可能需要在最後一個命令的輸出文件名末尾添加一個擴展名。

你可以這樣做:

cc Anna_program.c other_file.o -o Anna_program 

這將結合前面兩個步驟。

你應該記住的是,cc(或gcc)實際上不是編譯器,而是一個簡單的編譯管理器。在引擎蓋下,他們運行其他程序,在構建程序時執行不同的步驟。默認情況下,cc將嘗試採取您提供的內容並生成可執行文件(a.out),根據您提供的內容根據需要運行儘可能多的步驟。你可以傳遞它的標誌,比如-c來告訴它只能以部分方式(編譯和組裝,在這種情況下)。

對於C的步驟是預處理(由程序cpp完成),編譯(由cc1完成),組裝(通過as完成),和連接(通過ld完成)。

ccgcc命令決定需要做什麼,然後運行這些其他程序來完成它。