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