2013-09-22 22 views
2

我在一個簡單的C代碼中做了一個平庸的行爲,我正在爲教育目的而做。鐺如果至少沒有使用-O2,連接器就會失敗

如果我使用低於-O2的東西進行編譯,它會在鏈接編輯期間中斷此輸出。

$ make 
clang -Wall -march=native -pipe -c -g -D_DEBUG_ main.c 
clang -Wall -march=native -pipe -c -g -D_DEBUG_ functions.c 
clang -Wall -o main main.o functions.o 
Undefined symbols for architecture x86_64: 
    "_getbit", referenced from: 
     _getValueFromMatrix in functions.o 
    "_setbit", referenced from: 
     _populateMatrix in functions.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 
make: *** [main] Error 1 

我不知道這是否有幫助,但是,這裏是執行setbit();和getbit();

inline void setbit(uint64_t *inteiro, unsigned char pos) { 
    *(uint64_t*)inteiro |= (uint64_t)1 << pos; 
} 

inline bool getbit(uint64_t inteiro, unsigned char pos) { 
    return (inteiro & ((uint64_t)1 << pos)); 
} 

編輯:

functions.h

#ifndef __FUNCTIONS_H__ 
#define __FUNCTIONS_H__ 

/* Funções para manipulação de bits */ 

inline void setbit(uint64_t *, unsigned char); 

inline void clearbit(uint64_t *, unsigned char); 

inline bool getbit(uint64_t, unsigned char); 

inline unsigned char getbitChar(uint64_t, unsigned char); 

char *uint64_t2bin(uint64_t, char *, int); 

#endif 

包括main.c中

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <stdbool.h> 
#include <string.h> 

#include "errors.h" 
#include "const.h" 
#include "types.h" 
#include "functions.h" 
+0

setbit和getbit在main.c或functions.c中定義?或者在functions.c中包含的其中一個頭文件中? –

+0

是的,它們在functions.h中: inline void setbit(uint64_t *,unsigned char); inline bool getbit(uint64_t,unsigned char); –

+0

這些函數的實現在哪裏定義?我想任何人給你一個明確的答案,你需要顯示所有的代碼。但似乎編譯器沒有看到setbit和getbit的定義。也許它們不在你給編譯器的文件中,也許它們被一些#ifdefs隱藏,但是編譯器沒有看到setbit和getbit的定義。 –

回答

1

inline只有在.h文件中存在該函數的定義時纔是正確的。它基本上告訴編譯器它不應該爲每個編譯單元(你的.c文件)中的函數生成一個代碼。

如果在.h文件中沒有這樣的定義,就像在這裏看到的一樣,根本就不使用inline,它只是沒有意義。

如果您擔心的是您定義inline功能的單位中其他功能的效率,那麼您確實不需要這些功能。編譯器將內聯任何它已經實現的功能,並且其標準認爲它值得這樣做。

如果您確實希望將定義顯示在頭文件中,以便所有單位都可以看到定義,則使用然後使用inline。在這種情況下,您必須在一個單元中包含函數的「實例化」,以確保代碼只發布一次:

extern inline void setbit(uint64_t *, unsigned char); 
extern inline void clearbit(uint64_t *, unsigned char); 
extern inline bool getbit(uint64_t, unsigned char); 
extern inline unsigned char getbitChar(uint64_t, unsigned char); 
+0

謝謝!我已經在我的functions.c文件和function.h文件中將所有這些函數聲明爲extern inline。現在它編譯成功。以防萬一:extern inline和static inline之間有什麼區別? –

+0

@ViníciusFerrão,那不好。不要在'.h'文件中聲明它們是'extern inline':'.h'文件中的'inline','.c'中的'extern inline'。使用'static inline',您可以在每個編譯單元中生成一個獨立的函數副本。也許看看http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ –

0

內聯函數沒有任何外部定義,所以當編譯器無法將它們內聯(它不會在-O0處執行),鏈接器無法找到定義, d出現錯誤結果。最簡單的修復方法是將inline更改爲static inline。非靜態內聯很難使用,令人困惑,並且通常無用。

+0

我不同意。如果'.h'文件中有定義,'inline'是正確的選擇。如果在.h文件中沒有這樣的代碼,就像在這裏看到的那樣,只是根本不使用'inline',它沒有任何意義。 –

+0

在OP的情況下,頭文件中有代碼。如果你使用不帶'static'的'inline',你必須安排一些翻譯單元,用'extern'聲明函數,以便發出定義。不幸的是,有歷史編纂者處理這個可怕的錯誤(又名「GNU inline」),使其成爲一個棘手的問題。使用'static inline'可以確保你永遠不必處理這個問題。代碼將在每次使用時被內聯一次,並且/或者每個使用它的翻譯單元發出一次,由編譯器自行決定。 –

相關問題