类型定义为复杂的数据类型 [英] Typedefs for complex data types

查看:141
本文介绍了类型定义为复杂的数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解ç如何处理复杂类型定义的底层机制,从语法的角度来看。

考虑下面(包括在问题结尾的参考文献)下面的例子。


 的typedef INT(* P1D)[10];


  
  

是正确的声明,即P1D这里是一个指针数组
  10的整数只是因为它是使用数组类型的声明下。
  注意,这是不同于

 的typedef为int * P1D [10];


  
  

这将使P1D 10指针数组的名称int类型。


所以,如果我认为运营商precedence两个例子(我会重写它们):

 为int * P1D [10]; //变为...
为int * P1D [10];

所以,在阅读左到右,并使用运营商precedence,我得到:指针为int类型,名为P1D,尺寸10,这是错误的。至于其他的/第一种情况:

  INT(* P1D)[10];

这点我读作P1D为指针类型为int,并且是10个这样的元素的数组,这也是错误的。

有人能解释适用于确定这些类型定义的规则?我想将它们应用到函数指针,以及,我希望这种讨论也将解释背后常量管型(逻辑即:指向常量数据VS常量指针可变数据)。

感谢您。

参考文献:



  1. ç教程:指向数组的指针:<一href=\"http://www.taranets.net/cgi/ts/1.37/ts.ws.pl?w=329;b=285\">http://www.taranets.net/cgi/ts/1.37/ts.ws.pl?w=329;b=285

  2. 操作precedence: http://www.swansontec.com/sopc.html


解决方案

我的一个教授写的 这个小指南,阅读这类声明 <中/ I> 。不妨一读,这将是值得的,希望回答任何问题。

一切归功于里克·奥德( http://cseweb.ucsd.edu/~ricko/

 的右左的规则是破译℃的完全正规则
声明。它也可以是在创建它们是有用的。首先,符号。读     *作为指针 - 总是在左侧
     []为阵 - 总是在右侧
     ()为函数返回 - 总是在右侧当你遇到他们在声明中。步骤1
------
找到的标识符。这是你的起点。然后对自己说,
标识符。你开始你的宣言。第2步
------
只看标识符的右边的符号。比如说,如果你发现()
在那里,那么你就知道这是一个函数的声明。那么你
然后将产生标识符是函数返回。或者,如果你发现了
[]那里,你会说:标识符是数组。继续向右直到
你用完了符号*或*创出* *右括号)。 (如果碰到
左括号,这是一个()符号的开始,即使有
在括号中的东西。低于更多)。第3步
------
看符号标识符的左侧。如果它不是一个我们的
上述(比如说,类似INT)的符号,只是说出来。否则,翻译
它成英文使用上面的表。一直走,直到离开你用完
符号*或*击中左*括号(A *。直到你形成你的宣言现在重复步骤2和3。这里有一些
例子:     INT * P [];1)找到标识符。 INT * P [];
                                  ^
   普实2)向右移动,直到出符号或右括号命中。
                             INT * P [];
                                   ^^
   p为阵列3)不能再向右移动(出符号),因此向左移动,找到:
                             INT * P [];
                                 ^
   p是指针数组4)继续下去离开了,找到:
                             INT * P [];
                             ^^^
   p是指向int的指针数组。
   (或p是一个数组,其中每个元素都是类型的指针为int)另一个例子:   为int *(* FUNC())();1)找到的标识符。为int *(* FUNC())();
                                    ^^^^
   func为2)向右移动。为int *(* FUNC())();
                                        ^^
   FUNC是函数返回3)不能向右移动了,因为右括号,所以左边移动。
                             为int *(* FUNC())();
                                   ^
   FUNC是函数返回指针4)不能向左移动​​了,因为左括号,这样继续下去
   对。为int *(* FUNC())();
                                           ^^
   FUNC是函数返回函数指针返回5)无法向右移动了,因为我们出来的符号,所以要离开了。
                             为int *(* FUNC())();
                                 ^
   FUNC是函数返回的指针函数返回指针6)最后,一直走离开,因为没有什么留下的权利。
                             为int *(* FUNC())();
                             ^^^
   FUNC是函数返回的指针函数返回指向int的指针。
正如你所看到的,这个规则可以说是相当有用的。你也可以用它来
合理性检查自己,而你正在创建申报,并给予
你在哪里把下一个符号和括号是否暗示
是必要的。一些声明看起来要复杂得多,他们是由于阵
尺寸和参数列表以原型形式。如果你看到[3],这是
读作的阵列(尺寸3)......。如果你看到(字符*,INT)那读
作为功能期待(字符*,int)和返回......。这里有一个有趣的
一:                 INT(*(* fun_one)(字符*,双))[9] [20];我不会去通过每个步骤破译这一个。好。它的:     fun_one是函数指针期待(字符*,双面)和
      返回指针为int数组(尺寸为20)的阵列(大小9)。正如你所看到的,它不是那么复杂,如果你摆脱数组大小的
和参数列表:     INT(*(* fun_one)())[] [];你可以破译这种方式,然后放入数组大小和论证
后来列出。一些最后的话:这是很可能使使用这个法则非法声明,
所以有什么用C是合法的一些知识是必要的。例如,
如果上面已经:     为int *((* fun_one)())[] [];这本来是fun_one是函数指针数组的数组返回
                                          ^^^^^^^^^^^^^^^^^^^^^^^^
指针为int。由于函数不能返回数组,但只有一
指向数组的指针,该声明是非法的。
非法的组合包括:     []() - 不能有函数数组
     ()() - 不能有一个返回函数的函数
     ()[] - 不能返回一个数组的函数在上述所有情况下,你会需要一套括号中绑定一个*
在这些顺序()和[]右侧符号之间的左符号
对于声明是合法的。下面是一些合法的和非法的例子:INT I;一个int
INT * P;一个int指针(PTR为int)
int类型的[]; int数组
INT f()的;函数返回一个int
INT **页;一个指向一个int指针(PTR到PTR为int)
INT(* PA)[];一个指向int数组
INT(* PF)();指向一个函数返回一个int
INT * AP []; INT指针数组(师生比的数组整数)
INT氨基酸[] [];的整数数组的数组
INT AF []();过早返回一个int函数数组(非法)
INT * FP();函数返回一个int指针
INT FA()[];一个函数返回int数组(非法)
INT FF()();一个函数返回一个函数返回一个int
                                (非法)
INT *** PPP;一个指针的指针为int指针
INT(** PPA)[];一个指针的指针int数组
INT(** PPF)();指针指向一个函数返回一个int
为int *(* PAP)[];一个指向INT指针数组
INT(* PAA)[] [];一个指向整数数组的数组
INT(* PAF)[]();指针的函数返回一个int数组
                                (非法)
为int *(* PFP)();指向一个函数返回一个int指针
INT(* PFA)()[];指向一个函数返回int数组
                                (非法)
INT(* PFF)()();一个指针的函数返回一个函数
                                返回一个int(非法)
INT **应用[];指针为int的指针数组
INT(APA * [])[];指针数组以整数数组
INT(* APF [])();指针数组给函数返回一个int
INT * AAP [] []; INT指针数组的数组
INT AAA [] [] [];整型数组的数组的数组
INT AAF [] []();功能数组的数组返回一个int
                                (非法)
INT * AFP []();的返回int的函数指针数组(非法)
INT AFA []()[];函数数组返回int数组
                                (非法)
INT AFF []()();过早返回函数的函数数组
                                返回一个int(非法)
INT ** FPP();函数返回一个指向一个int指针
INT(* FPA())[];函数返回一个指向int数组
INT(* FPF())();函数返回一个指针的函数
                                返回一个int
INT * FAP()[];函数返回int数组的指针(非法)
诠释FAA()[] [];一个函数返回的int数组的数组
                                (非法)
INT FAF()[]();一个函数返回一个函数数组
                                返回一个int(非法)
INT * FFP()();一个函数返回一个函数
                                返回一个int指针(非法)

I am attempting to understand the underlying mechanics of how C handles complex typedefs, from a syntax perspective.

Consider the following examples below (references included at end of the question).

typedef int (*p1d)[10];

is the proper declaration, i.e. p1d here is a pointer to an array of 10 integers just as it was under the declaration using the Array type. Note that this is different from

typedef int *p1d[10];

which would make p1d the name of an array of 10 pointers to type int.

So, if I consider operator precedence for both examples (I'll rewrite them):

int *p1d[10]; // Becomes ...
int* p1d[10];

So, reading left-to-right, and using operator precedence, I get: "Pointer to type int, named p1d, of size 10", which is wrong. As for the other/first case:

int (*p1d)[10];

Which I read as "p1d is a pointer, of type int, and is an array of 10 such elements", which is also wrong.

Could someone explain the rules applied for determining these typedefs? I would like to apply them to function pointers as well, and I'm hoping this discussion will also explain the logic behind const casts (ie: pointer to constant data vs const pointer to variable data).

Thank you.

References:


  1. C Tutorial: Pointers to Arrays: http://www.taranets.net/cgi/ts/1.37/ts.ws.pl?w=329;b=285
  2. Operator Precedence: http://www.swansontec.com/sopc.html

解决方案

One of my professors wrote this little guide to reading these kinds of declarations. Give it a read, it'll be worth your while and hopefully answer any questions.

All credit goes to Rick Ord (http://cseweb.ucsd.edu/~ricko/)

The "right-left" rule is a completely regular rule for deciphering C
declarations.  It can also be useful in creating them.

First, symbols.  Read

     *      as "pointer to"         - always on the left side
     []     as "array of"           - always on the right side
     ()     as "function returning"     - always on the right side

as you encounter them in the declaration.

STEP 1
------
Find the identifier.  This is your starting point.  Then say to yourself,
"identifier is."  You've started your declaration.

STEP 2
------
Look at the symbols on the right of the identifier.  If, say, you find "()"
there, then you know that this is the declaration for a function.  So you
would then have "identifier is function returning".  Or if you found a 
"[]" there, you would say "identifier is array of".  Continue right until
you run out of symbols *OR* hit a *right* parenthesis ")".  (If you hit a 
left parenthesis, that's the beginning of a () symbol, even if there
is stuff in between the parentheses.  More on that below.)

STEP 3
------
Look at the symbols to the left of the identifier.  If it is not one of our
symbols above (say, something like "int"), just say it.  Otherwise, translate
it into English using that table above.  Keep going left until you run out of
symbols *OR* hit a *left* parenthesis "(".  

Now repeat steps 2 and 3 until you've formed your declaration.  Here are some
examples:

     int *p[];

1) Find identifier.          int *p[];
                                  ^
   "p is"

2) Move right until out of symbols or right parenthesis hit.
                             int *p[];
                                   ^^
   "p is array of"

3) Can't move right anymore (out of symbols), so move left and find:
                             int *p[];
                                 ^
   "p is array of pointer to"

4) Keep going left and find:
                             int *p[];
                             ^^^
   "p is array of pointer to int". 
   (or "p is an array where each element is of type pointer to int")

Another example:

   int *(*func())();

1) Find the identifier.      int *(*func())();
                                    ^^^^
   "func is"

2) Move right.               int *(*func())();
                                        ^^
   "func is function returning"

3) Can't move right anymore because of the right parenthesis, so move left.
                             int *(*func())();
                                   ^
   "func is function returning pointer to"

4) Can't move left anymore because of the left parenthesis, so keep going
   right.                    int *(*func())();
                                           ^^
   "func is function returning pointer to function returning"

5) Can't move right anymore because we're out of symbols, so go left.
                             int *(*func())();
                                 ^
   "func is function returning pointer to function returning pointer to"

6) And finally, keep going left, because there's nothing left on the right.
                             int *(*func())();
                             ^^^
   "func is function returning pointer to function returning pointer to int".


As you can see, this rule can be quite useful.  You can also use it to
sanity check yourself while you are creating declarations, and to give
you a hint about where to put the next symbol and whether parentheses
are required.

Some declarations look much more complicated than they are due to array
sizes and argument lists in prototype form.  If you see "[3]", that's
read as "array (size 3) of...".  If you see "(char *,int)" that's read
as "function expecting (char *,int) and returning...".  Here's a fun
one:

                 int (*(*fun_one)(char *,double))[9][20];

I won't go through each of the steps to decipher this one.

Ok.  It's:

     "fun_one is pointer to function expecting (char *,double) and 
      returning pointer to array (size 9) of array (size 20) of int."

As you can see, it's not as complicated if you get rid of the array sizes
and argument lists:

     int (*(*fun_one)())[][];

You can decipher it that way, and then put in the array sizes and argument
lists later.

Some final words:

It is quite possible to make illegal declarations using this rule,
so some knowledge of what's legal in C is necessary.  For instance,
if the above had been:

     int *((*fun_one)())[][];

it would have been "fun_one is pointer to function returning array of array of
                                          ^^^^^^^^^^^^^^^^^^^^^^^^
pointer to int".  Since a function cannot return an array, but only a 
pointer to an array, that declaration is illegal.


Illegal combinations include:

     []() - cannot have an array of functions
     ()() - cannot have a function that returns a function
     ()[] - cannot have a function that returns an array

In all the above cases, you would need a set of parens to bind a *
symbol on the left between these () and [] right-side symbols in order
for the declaration to be legal.

Here are some legal and illegal examples:

int i;                  an int
int *p;                 an int pointer (ptr to an int)
int a[];                an array of ints
int f();                a function returning an int
int **pp;               a pointer to an int pointer (ptr to a ptr to an int)
int (*pa)[];            a pointer to an array of ints
int (*pf)();            a pointer to a function returning an int
int *ap[];              an array of int pointers (array of ptrs to ints)
int aa[][];             an array of arrays of ints
int af[]();             an array of functions returning an int (ILLEGAL)
int *fp();              a function returning an int pointer
int fa()[];             a function returning an array of ints (ILLEGAL)
int ff()();             a function returning a function returning an int
                                (ILLEGAL)
int ***ppp;             a pointer to a pointer to an int pointer
int (**ppa)[];          a pointer to a pointer to an array of ints
int (**ppf)();          a pointer to a pointer to a function returning an int
int *(*pap)[];          a pointer to an array of int pointers
int (*paa)[][];         a pointer to an array of arrays of ints
int (*paf)[]();         a pointer to a an array of functions returning an int
                                (ILLEGAL)
int *(*pfp)();          a pointer to a function returning an int pointer
int (*pfa)()[];         a pointer to a function returning an array of ints
                                (ILLEGAL)
int (*pff)()();         a pointer to a function returning a function
                                returning an int (ILLEGAL)
int **app[];            an array of pointers to int pointers
int (*apa[])[];         an array of pointers to arrays of ints
int (*apf[])();         an array of pointers to functions returning an int
int *aap[][];           an array of arrays of int pointers
int aaa[][][];          an array of arrays of arrays of ints
int aaf[][]();          an array of arrays of functions returning an int
                                (ILLEGAL)
int *afp[]();           an array of functions returning int pointers (ILLEGAL)
int afa[]()[];          an array of functions returning an array of ints
                                (ILLEGAL)
int aff[]()();          an array of functions returning functions
                                returning an int (ILLEGAL)
int **fpp();            a function returning a pointer to an int pointer
int (*fpa())[];         a function returning a pointer to an array of ints
int (*fpf())();         a function returning a pointer to a function
                                returning an int
int *fap()[];           a function returning an array of int pointers (ILLEGAL)
int faa()[][];          a function returning an array of arrays of ints
                                (ILLEGAL)
int faf()[]();          a function returning an array of functions
                                returning an int (ILLEGAL)
int *ffp()();           a function returning a function
                                returning an int pointer (ILLEGAL)

这篇关于类型定义为复杂的数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆