Re: [問題] extern "C"的問題

看板C_and_CPP (C/C++)作者 (我要加入劍道社!)時間16年前 (2009/06/10 14:59), 編輯推噓8(805)
留言13則, 6人參與, 最新討論串4/5 (看更多)
※ 引述《QQ29 (我愛阿蓉)》之銘言: : 標題: Re: [問題] extern "C"的問題 : 時間: Wed Jun 10 13:46:23 2009 : : 不好意思 我現在自己想問題測試 其實我對extern "C"真的不是很懂 : z大說的我明白 : 而我現在寫法是這樣如下 : : main.cpp : #include <iostream> : using namespace std; : #include "test.h" 先挑一個和標題無關的錯誤:using namespace 不應該寫在任何 #include 之前 這算是滿糟糕的寫法,因為 compiler 不會報錯, 只有在發生名稱衝突時才吐一堆不知所云的訊息,而你不會想到是這行寫錯地方 : 以上這樣寫 是為了讓 test.c不去include test.h(我那個struct .c必須用到) : 這樣可以compile過 但是我繼續想辦法try : 我將extern "C"拿掉 test.c改成test.cpp : 竟然就認不到了........... 你的「認不到」是指 compiler error 還是 link error? 錯誤訊息是什麼? main.cpp: #include "test.h" int main() { foo(); return 0; } test.h: #ifndef TEST_H #define TEST_H struct FU; FU* foo(); #endif // TEST_H test.cpp typedef struct FF { int x, y; } FU; FU* foo() { return NULL; } 以上的 code 可以順利 compile、link 並執行 但其中卻隱含了非常邪惡的地方 那就是在 test.h 中並沒有 typedef 的敘述 所以你在 test.cpp 中雖然使用了 typedef 但含入 test.h 的 main.cpp 中並不知道「FF」這個 struct 的存在 它得到的資訊僅是: foo() 是一個函式,不接受參數,傳回一個指向 FU 的指標 而 test.cpp 呢?因為 typedef 的緣故,它知道 FU 只是 FF 的別名, 所以你定義的 foo() 是: foo() 是一個函式,不接受參數,傳回一個指向 FF 的指標 所以你的定義和宣告已經如同政客般言行不一了 但運氣很好 (從另一個角度來看,應該說不好才對) 的是 C++ 的函式回傳型別並不會成為 name mangling 的一部份 所以上述的 foo() 雖然本質上是不同的 但它們在編譯時會變成相同的 symbol 因此上述的程式可以順利連結 如果你改成以下的寫法,就過不了關了: test.h: #ifndef TEST_H #define TEST_H struct FU; void foo(FU*); #endif // TEST_H test.cpp typedef struct FF { int x, y; } FU; void foo(FU*) { return; } : 原因很想請板上高手解釋一下 : : 因為我知道struct改成class的話 上面的改法 就不會有問題 C++ 中 struct 和 class 幾乎完全相同, 唯一的不同在於 struct 預設成員為 public 而 class 預設成員為 private 其它使用方法完全相同 : 1.為什麼struct卻不能呢? 因為你用了 typedef : 2.一開始我這樣故意把.c的include .h拿掉是不是一個好的作法? 不是 因為你的 .c 明顯是要實作 .h 提供的介面 不去 include 是自找麻煩 : 不然勢必extern "C"就要寫在main ==>extern "C"{include "test.h"} 一般會這樣寫: #ifndef TEST_H #define TEST_H #ifdef __cplusplus extern "C" { #endif // __cplusplus typedef struct FF { int x, y; } FF; FF* foo(void); #ifdef __cplusplus } // end of extern "C" #endif // __cplusplus #endif // TEST_H 這樣你的 test.h 就能讓 C/C++ compiler 同時使用 : → QQ29:你好~typedef我認知是 定義struct並且給一個(以上)別名之類的 06/10 14:04 : → QQ29:我是不清楚 看很多他人寫的程式都很愛使用typedef struct 06/10 14:05 : → QQ29:但是實際上的好處以及在我問的問題上 差異在哪裡!! 06/10 14:05 C 裡面的 struct 名稱不能直接當型別使用,需要在前面多加 struct 關鍵字: struct Point { int x, y; }; void foo() { Point p; // error struct Point p; // OK } 所以很多人會這樣寫: typedef struct Point { int x, y; } Point; void foo() { Point p; // OK } 但是 C++ 已經沒有這層限制了: struct Point { int x, y; }; class Line { Point start, end; }; void foo() { Point p; // OK Line l; // OK } 大大您也是 C_and_CPP 的常客了,也該積極了解自己寫出每行 code 的真正意義。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 219.87.151.2

06/10 15:02, , 1F
謝謝你 我會仔細研究一下 我很積極只是自己功力不夠@@
06/10 15:02, 1F

06/10 15:02, , 2F
還是感謝你 thx
06/10 15:02, 2F

06/10 15:09, , 3F
推 littleshan 的詳盡解說
06/10 15:09, 3F

06/10 15:22, , 4F
以上的 code 可以順利 compile、link 並執行<<<上面這邊我用
06/10 15:22, 4F

06/10 15:22, , 5F
VC的話 他link不到耶 所以我說他認不到...
06/10 15:22, 5F

06/10 15:37, , 6F
請問文中的__cplusplus是要在哪裡define呢?
06/10 15:37, 6F

06/10 15:38, , 7F
推l大的解釋:)
06/10 15:38, 7F

06/10 15:40, , 8F
__cplusplus compiler 會自己定義
06/10 15:40, 8F

06/10 15:56, , 9F
原來是不能直接用struct的型別名稱,而不是不能struct s1{;};
06/10 15:56, 9F

06/10 15:57, , 10F
我以前是看google搜尋到的文件,解釋有誤,難怪有經驗的前輩
06/10 15:57, 10F

06/10 15:57, , 11F
都說不先看官方manual卻反而去google,這是捨本逐末的作法
06/10 15:57, 11F

06/10 16:19, , 12F
是因為compiler會最優先定義__cplusplus所以ifdef才會成立嘛
06/10 16:19, 12F

06/10 16:19, , 13F
感覺是compile會在每個cpp最前面加上去define __cplusplus?
06/10 16:19, 13F
文章代碼(AID): #1ABrdOhE (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
以下文章回應了本文
完整討論串 (本文為第 4 之 5 篇):
文章代碼(AID): #1ABrdOhE (C_and_CPP)