Re: [問題] 開成專案以後標頭檔&全域變數問題

看板C_and_CPP作者 (CJ Cat)時間9年前 (2014/12/19 16:02), 9年前編輯推噓2(201)
留言3則, 2人參與, 最新討論串3/3 (看更多)
※ 引述《defsrisars (阿轉)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : 1. void Deal_First(int *card,Player *P,int *flag); : 這一行會跑出編譯訊息 : [Note] expected 'int *' but argument is of type 'int (*)[52]' : 想請問是什麼意思呢? int * 跟 int(*) 是差在哪QQ : 我呼叫的地方是這樣寫的 : Deal_First(&card,A,&flag); card本身的型別已經是array of int array of X已經可以隱晦轉型成pointer to X了,不需要另外用&取位址 用&取位址&card的型別變成了pointer to an array of 52 ints int * = pointer to int int (*) [52] = pointer to an array of 52 ints 至於要怎麼看出等號左邊的型別等於右邊的英文 這牽扯到了right-left rule 這是C/C++把定義型別的一堆符號翻譯成英文的規則 從變數名稱開始,往右邊解讀 等到不能再往右了,就開始往變數名稱左邊開始解讀 順序又可以用括號來限制 括號內解讀完了,再把括號當作一個單位,如變數名稱一樣的方式往右再往左解讀 講得有點抽象,先用英文字母來示範一下好了 假設我有個變數叫做myVar,其定義如下 A B (C myVar) D E 1. 從myVar開始,往右解讀,馬上碰到括號,停止 2. 從myVar開始,往左解讀,碰到C,接著又碰到括號,停止 3. 括號內處理完了,現在以括號為單位,重來一次 4. 往右解讀,依序碰到D和E,停止 5. 左括號開始往左解讀,依序碰到B和A,結束 所以英文字母的解讀順序是 C D E B A 至於這些英文字母可以有哪些符號帶入,對應的英文又為何 請見以下清單: * myVar = pointer to a/an... & myVar = reference to a/an... myVar [n] = array of n... T myVar (a, b, etc.) = function that takes a, b, etc. as arguments and returns T T const myVar = a/an constant T 要把有名稱的變數定義轉換成單純的型態表示法 只要把myVar抽掉就好 遇到純型態表示法,如你說的 int * 和 int (*) [52] 想辦法把myVar插入到一個合法的位置(有辦法解讀的位置)再開始解讀就好 不用擔心,只會有一個合法的位置可以插入myVar 所以 int * myVar 用right-left rule解讀的時候會依序碰到的符號是 * int 英文就是 myVar is a pointer to int int (*myVar) [52] 用right-left rule解讀會依序碰到的符號則是 * [52] int 英文是 myVar is a pointer to 52 ints 用這個原則 可以很簡單地區分新手常常搞混的 constant pointer 和 pointer to constant int const * myVar 解讀時會依序碰到的符號是 * const int 所以英文是 myVar is a pointer to a constant int int * const myVar 解讀時會依序碰到的符號是 const * int 英文則是 myVar is a constant pointer to an int 至於 int const * const myVar 的英文則是 myVar is a constant pointer to a constant int const有個例外: const int myVar; int const myVar; 以上兩個例子都是myVar is a constant int 這種簡單的變數定義,通常採取第一種寫法 我也遇過很嚴格遵守right-left rule的人,他們採用第二種寫法 另外以下舉個複雜一點的例子 int const & (*myVar) [10] (int, float) 用right-left rule依序會碰到的符號順序是 * [10] (int, float) & const int 因此英文是(每兩行的第一行是英文,第二行是對照的符號) myVar is a pointer to an array of 10 functions that take an int and myVar * [10] ( int , a float as arguments and return a reference to a constant int float ) & const int : 其中card跟flag是宣告int : A是用malloc做出指向結構Player(我有typedef了)的指標 : struct player * A = (struct player*)malloc(sizeof(struct player)); : 2. 然而最主要的錯誤是出在 : 14 34 C:\Users\PC\Desktop\期末專題Dev\Deal_First.c [Error] : 'flower_table' undeclared (first use in this function) : 14 64 C:\Users\PC\Desktop\期末專題Dev\Deal_First.c [Error] : 'number_table' undeclared (first use in this function) : 也就是下方程式碼的78行 : 我看起來的認知是compiler覺得我的flower_table跟number_table沒有宣告 : 但洽p我~行宣均o不是應該式h﹃︹︽﹄.︷裡面宣均o為全域變數丑l嗎? : (我情{案應該開的沒問獺d~都有連結到,這行//插|央o央t執行丑l) : 另外插|是想請問有沒有辦炕w把這個~行放間o標頭檔(全域變數放間o標頭檔?) 你要先搞清楚宣告(declaration)和定義(definition)的差別 整個程式可以宣告同一個變數或函式很多次 但是必須在一個.c檔內定義一次、且僅此一次 在一個.c檔內,變數和函式要宣告過才可以使用 定義一個變數的方式,常常被誤稱為"宣告" int x = 10; //這是定義 宣告一個全域變數的方式,則是用extern 這是告訴compiler接下來的程式可以使用這個被宣告的全域變數 而這個被宣告的全域變數,在別的地方定義 linker則會把變數定義跟使用變數的程式部分做連結 extern int x; //這是宣告 你在main.c定義了flower_table和number_table 但是在Deal_First.c裡面沒有宣告 所以你需要在Deal_First.c的開頭加上 extern const char flower_table[4]; extern char number_table[13][BUF_SIZE]; : 然後又像extern結構的用法一樣不要重複宣告呢? 沒有extern struct這種東西 寫了也沒有用 : 然後如果有哪裡是很爛的寫法該做修改請告訴我謝謝QQ 看起來是個目的非常特化的小作業(或小練習?) 我覺得沒有什麼爛不爛的問題 寫得出來可以交差就好了 -- Ming-Lun "Allen" Chou Web http://AllenChou.net Twitter http://twitter.com/TheAllenChou LinkedIn http://www.linkedin.com/in/MingLunChou -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 75.84.49.95 ※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1418976156.A.9EF.html ※ 編輯: cjcat2266 (75.84.49.95), 12/19/2014 16:07:16

12/19 18:50, , 1F
謝謝您!!非常詳細(沒想到解讀順序就這麼博大精深)
12/19 18:50, 1F

12/19 18:52, , 2F
不好意思~想另外請教您一些問題(私信)
12/19 18:52, 2F

12/19 22:28, , 3F
好文
12/19 22:28, 3F
文章代碼(AID): #1KazkSdl (C_and_CPP)
文章代碼(AID): #1KazkSdl (C_and_CPP)