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

作者: cjcat2266 (CJ Cat)   2014-12-19 16:02:33
※ 引述《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
看起來是個目的非常特化的小作業(或小練習?)
我覺得沒有什麼爛不爛的問題
寫得出來可以交差就好了
作者: defsrisars (阿轉)   2014-12-19 18:50:00
謝謝您!!非常詳細(沒想到解讀順序就這麼博大精深)不好意思~想另外請教您一些問題(私信)
作者: gg1122 (99通未接來電)   2014-12-19 22:28:00
好文

Links booklink

Contact Us: admin [ a t ] ucptt.com