a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 64|回复: 1

[综合辅导] Linux辅导:轻松学习typedef的四个用途

[复制链接]
发表于 2012-8-4 12:07:07 | 显示全部楼层 |阅读模式
用途一:   定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:# [; R; S- z9 J3 \9 Q4 }
  char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,. S' D# H+ J! @5 H, A0 O. |( T$ B
  // 和一个字符变量;
- M% [3 s. ^& m1 u& G  以下则可行:# O' V9 m6 ^; V, ~$ |
  typedef char* PCHAR; // 一般用大写; Z. E4 E5 m- b4 [* A
  PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针3 H. }, e9 b+ k8 k
  虽然:; Y4 e2 M: N2 Q) [
  char *pa, *pb;
6 r6 w4 Y5 M/ {7 y: o- J6 O8 n  y  也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。
6 f) q0 \- }( }  用途二:( k: w# ~# k/ @5 E
  用在旧的C代码中(具体多旧没有查),帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名 对象名,如:
( U. R, Z* i; c2 M6 Z8 u% i; z  struct tagPOINT1
/ d: O" y" y  v/ S4 V- y! @; @% h1 q! \! Z  {/ s! z* }3 X! _0 Y
  int x;" W: \0 c, @% r
  int y;
$ ~4 F9 K' I. L1 d) }' P; ~  };: R, F# H. E. ]2 x
  struct tagPOINT1 p1;. N  c7 E: Z# O3 d
  而在C++中,则可以直接写:结构名 对象名,即:2 G9 d6 c; q2 V' U" j9 w
  tagPOINT1 p1;" A$ O3 Y# @. C# S
  估计某人觉得经常多写一个struct太麻烦了,于是就发明了:! u7 v7 _& m7 ^
  typedef struct tagPOINT
* R& t% F; M( c# B  U7 }9 e( _: X  {0 n' B# S/ C+ t" q( B+ W$ d, i' E
  int x;4 q5 r( B. S6 ^
  int y;7 i1 [. b$ D. f4 h* u" A
  }POINT;
4 o0 `. G* B4 V+ t  POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候1 D& k- t: r! s. G+ }2 w# ^
  或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。5 C$ V" X. L8 S- z0 F3 s
用途三:
+ r0 B( {; Y: f: }  用typedef来定义与平台无关的类型。
' w; U& B' j$ ]: o8 E' c( J1 r# {  比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:
$ n7 Z2 w8 q" f5 A) r4 q- z  typedef long double REAL;% }6 G# i: ?& }
  在不支持 long double 的平台二上,改为:
. Z& W' I0 ~) |! }8 ~+ g  typedef double REAL;/ n! Q  U& `: z* z/ d( j
  在连 double 都不支持的平台三上,改为:
1 d' y3 Z* e  l( i  typedef float REAL;
4 e# c8 y, _/ x9 o/ |" b" c* u  也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。$ @' L- z# N% ~
  标准库就广泛使用了这个技巧,比如size_t。
, V8 B$ Z* `7 Q
# U% I( j' Q* }* @9 D% i: Y  另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健(虽然用宏有时也可以完成以上的用途)。
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:07:08 | 显示全部楼层

Linux辅导:轻松学习typedef的四个用途

</p>  用途四:; w+ M, E1 D; C. D0 R
  为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版。举例:
0 s7 |, Z. A5 }2 W  1. 原声明:int *(*a[5])(int, char*);
' ~5 T$ y2 ^$ ^/ G7 c* ]( u$ k  变量名为a,直接用一个新别名pFun替换a就可以了:
* x) _6 @* f6 S; ~: K  typedef int *(*pFun)(int, char*);
: K6 {; C7 Z. X  原声明的最简化版:
3 _3 v! n1 }0 m% V* x  pFun a[5];2 y6 v8 l; I. a7 ~4 h6 z
  2. 原声明:void (*b[10]) (void (*)());
# h) N" X- u5 w2 [: }  变量名为b,先替换右边部分括号里的,pFunParam为别名一:4 |0 z4 V9 m' S" _( t
  typedef void (*pFunParam)();! A) T- A' i; z* \7 l0 k
  再替换左边的变量b,pFunx为别名二:
, N0 B6 b; A& A  typedef void (*pFunx)(pFunParam);/ x, i# `' u: j; G( T) e9 d$ B3 L% u( H
  原声明的最简化版:
5 ~( \; ]* P0 o% Z4 o8 t8 V  pFunx b[10];) c& t4 r+ j) a9 v) K2 m! l) D
3. 原声明:doube(*)() (*e)[9];
/ P7 W9 _( \4 l  o3 [' C  变量名为e,先替换左边部分,pFuny为别名一:6 Z3 m1 C4 K" w) u! H
  typedef double(*pFuny)();
* Y( b! H$ ]+ H3 R6 {7 ]  再替换右边的变量e,pFunParamy为别名二5 y: t; j5 W, c* J/ K& {
  typedef pFuny (*pFunParamy)[9];
/ w. D( Y1 k/ ?; m  原声明的最简化版:
3 v% p9 A6 A+ `" Z! t; F$ J  pFunParamy e;
9 }2 t! e$ [; e, h% h  理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例:4 D! H$ \, W4 ]% g3 n4 x
  int (*func)(int *p);
  D( o. Z  _8 o' N5 X$ |+ q  首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明(*func)是一个函数,所以func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值类型是int。' u0 b7 W, l  H) {
  int (*func[5])(int *);
; E6 j8 R1 Y& I  Q3 ^  func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func的元素是指针(注意这里的*不是修饰 func,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。- G2 [( C! Y& d
  也可以记住2个模式:
1 |1 C  ]; A! Q2 p  type (*)(....)函数指针0 ~! h3 ^  w) W9 M0 _
  type (*)[]数组指针
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-21 16:28 , Processed in 0.560322 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表