你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

你知道为什么大家编程喜欢用typedef?

[复制链接]
gaosmile 发布时间:2020-5-11 19:41
1. typedef 的基本使用' b8 [2 O6 a, Y" X" m, f
1.1 typedef与结构体的结合使用" s6 n1 C1 `# z7 a/ x  x
typedef 是 C 语言的一个关键字,用来给某个类型起个别名,也就是给C语言中已经存在的一个类型起一个新名字。大家在阅读代码的过程中,会经常见到 typedef 与结构体、联合体、枚举、函数指针声明结合使用。比如下面结构体类型的声明和使用:

  1. ) k4 }/ x1 o) J$ Q; h0 N" |
  2. struct student$ I. A" u* Y' u
  3. {6 i; b" \- G: n" F
  4.   char name[20];" q( }( H& h2 p6 J5 V0 o+ R1 c% x
  5.   int  age;, P+ m/ [! b2 \! y' a; s
  6.   float score;" W* O7 f# s, \1 Q
  7. };
    : r) ^4 Y$ [3 S1 l
  8. struct student stu = {"wit", 20, 99};
复制代码
, q" w# q2 v: N  A1 n
在C语言中定义一个结构体变量,我们通常的写法是:
  1. " f: J# H3 N7 k; B+ x
  2. struct 结构体名 变量名;
复制代码
) S) Z0 _# U" ~- c4 H; E( l$ C
前面必须有一个struct关键字打前缀,编译器才会理解你要定义的对象是一个结构体变量。而在C++语言中,则不需要这么做,直接使用:结构体名 变量名就可以了
  1. 3 R+ ]+ d1 ?& V5 g( v! s1 N6 z4 Y
  2. struct student # h% M9 b- r( Z$ F/ G
  3. {( t  O) k9 L( e4 d
  4.   char name[20];, O1 ^. g* v3 r( @, i0 P
  5.   int age;, o/ t2 r& c3 L8 l6 m6 W. z$ v2 p" q+ f
  6.   float score; ( a4 z& K$ K# p+ W9 R
  7. };
    % N9 v  R# i* ^  D
  8. int main (void)
      r" H, U& `# K' z: a
  9. {+ n% D8 R7 C3 }
  10.   student stu = {"wit", 20, 99};5 v& ]. e6 E) Z( @$ k
  11.   return 0;
    ' X- y" f5 C* D# }+ n* t8 H
  12. }
复制代码

% w  f! Z& C/ k% t* @/ @
如果我们使用typedef,就可以给student声明一个别名student_t和一个结构体指针类型student_ptr,然后就可以直接使用student_t类型去定义一个结构体变量,不用再写struct,这样会显得代码更加简洁。

  1. 6 ]$ s: V- V7 L2 l8 f
  2. #include <stdio.h>3 U$ {3 `' i! E& X- L+ V: H: g
  3. typedef struct student
    , j- V% F# X9 f, ^& |  _* T  _
  4. {
    8 c# U1 g, y5 ~$ A& d8 x* Q2 d/ T
  5.   char name[20];
    8 ?5 F/ |) N% p; ~* ?
  6.   int  age;  d5 T. ^# |0 ]0 ~
  7.   float score;5 m; ]' X6 l" i2 S; o$ n
  8. }student_t, *student_ptr;7 R% J! ]% Z* n1 r5 i
  9. 4 F* ^6 K* X& c' g9 P+ H
  10. int main (void)( o0 V0 r& I4 S9 b
  11. {' |8 l- |9 w  \/ c1 F
  12.   student_t   stu = {"wit", 20, 99};( M# z: x4 C/ a; M5 z* ]0 `
  13.   student_t  *p1 = &stu;. z' u  q' T: t/ K. {
  14.   student_ptr p2 = &stu;; h) a0 ]7 w+ q& ]
  15.   printf ("name: %s\n", p1->name);' K# @8 k* Q. k
  16.   printf ("name: %s\n", p2->name);
    0 V7 W: Z% U  K* c3 a: a& D) M
  17.   return 0;
    ! U+ ?0 p- p; f. C6 V( S
  18. }
    - q0 U+ x, g9 }
  19. 程序运行结果:$ Z( |& b2 R' ^
  20. wit( F: k" n9 o! d" N. x( e! m2 E6 z
  21. wit
复制代码

5 ]; K2 e* Q9 D
1. 2 typedef 与数组的结合使用
typedef除了与结构体结合使用外,还可以与数组结合使用。定义一个数组,通常我们使用int array[10];即可。我们也可以使用typedef先声明一个数组类型,然后再使用这个类型去定义一个数组。

  1. ) E$ k$ _. U; y' J0 t; L8 b" j
  2. typedef int array_t[10];
    * H$ Y; s- ?& g  i. n
  3. array_t array;8 @# U- K- j+ K, w$ Z& l
  4. int main (void)+ l: H, I5 y+ r6 a. l, W
  5. {
    ( x& q) @: _; x7 X& e' x
  6.   array[9] = 100;
    ; x1 u' {  s3 b  d. {& ], ]) r/ h
  7.   printf ("array[9] = %d\n", array[9]);$ f1 K! v7 `/ t8 ?$ p# q- ?8 m! [
  8.   return 0;. C3 g% z7 _# O% s7 b
  9. }
复制代码
( t3 `) N- w8 w
在上面的demo程序中,我们声明了一个数组类型array_t,然后再使用该类型定义一个数组array,这个array效果其实就相当于:int array[10]。
9 i, _& C2 O/ |# C/ V! }
1.3 typedef 与指针的结合使用
& z! V' R! x5 n3 }) A

  1. ) t7 t' g( T% B& j
  2. typedef char * PCHAR;9 t9 {) b/ q& R# D9 Q" o
  3. int main (void)
    3 }* X# N$ B/ Z* ?6 x* P
  4. {6 J, t, @% Y0 Y! v
  5.     //char * str = "学嵌入式";# Y: P& t( F' T9 _0 l
  6.   PCHAR str = "学嵌入式";  |( N: t% l  ?$ [/ P# u! L# r
  7.   printf ("str: %s\n", str);
    ( e# z7 Y9 a$ t5 p" O
  8.   return 0;
    " d" W& \* H% o; _
  9. }
复制代码

% |4 [8 o/ M) Y; c
  q# S3 \. N# ^( Q- t
在上面的demo程序中,PCHAR 的类型是 char *,我们使用PCHAR类型去定义一个变量str,其实就是一个char *类型的指针。
1.4 typedef与函数指针的结合使用
定义一个函数指针,我们通常采用下面的形式:

  1. / z5 K9 ]7 c' t2 B1 k
  2. int (*func)(int a, int b);
复制代码

6 V/ v% C. N- f# o2 }
我们同样可以使用typedef声明一个函数指针类型:func_t

  1.   t4 {1 H5 i+ B4 F
  2. typedef int (*func_t)(int a, int b);
    , z- b, g8 ^5 u1 o! X- M* [  d
  3. func_t fp;  // 定义一个函数指针变量
复制代码
/ @6 n7 o8 K  Q6 e
写个简单的程序测试一下,运行OK:

  1. " ]$ u7 p  r1 D. ?" Q, ^
  2. typedef int (*func_t)(int a, int b);
      P/ r! D4 p7 q' z$ E: K
  3. int sum (int a, int b)
    ; L0 \# P, g1 v' y; A' v
  4. {
    0 z$ T: K; F! O' o2 D1 I6 x+ `
  5.   return a + b;
    ) z8 M* o( y' b0 A- m1 \$ k0 t
  6. } 4 S7 z) {5 ?" o8 N
  7. int main (void), {8 F1 b, L% c1 C6 V
  8. {4 b3 a* N& U4 V$ p  @: G7 w
  9.   func_t fp = sum;
    " j6 v8 h+ i7 Z! w9 v: h% T
  10.   printf ("%d\n", fp(1,2));
    ! D: ^7 T, L; ^2 I) T
  11.   return 0;
      O* {7 n3 S) V+ Q0 Q: u
  12. }
复制代码

& q$ Q) b0 n* I/ X
为了增加程序的可读性,我们经常在代码中看到下面的声明形式:

  1. % T0 T) }( l( k% x/ B6 v9 k
  2. typedef int (func_t)(int a, int b);
    " |& t) z) D) m( h$ A9 |- v4 e
  3. func_t *fp = sum;
复制代码

' i: S  i" C) \
函数都是有类型的,我们使用typedef给函数类型声明一个新名称:func_t。这样声明的好处是:即使你没有看到func_t的定义,也能够清楚地知道fp是一个函数指针,代码的可读性比上面的好。
% l: R: Z, C# W8 l
1.5 typedef与枚举的结合使用
/ ?  Z5 ~8 N6 ]
  1. 8 s, A/ W" C: L# Y
  2. typedef enum color8 g  X: {& g0 H4 l5 k6 A
  3. {
    9 O! Y6 a; n. P. E( L
  4.   red,6 ?. T; T3 v5 T) _8 @/ A: F% c- D
  5.   white,
    9 x7 ^( R. f8 S- i9 T
  6.   black,
    ) b4 x' v7 m8 \8 M
  7.   green,
    - S5 W0 g0 W) s" t* h9 w
  8.   color_num,& Y. n3 r; k' y8 G3 T
  9. } color_t;* a7 M' ^+ m1 v1 z2 M
  10. , k# ?% w8 n3 q  _: s8 J
  11. int main (void)* O' I" E3 n. ~) q
  12. {
    - _( i" S) m! n9 V
  13.   enum color color1 = red;: R5 E7 B5 ?6 N# T4 Y  K7 ]
  14.   color_t    color2 = red;" Z' j5 w: U' A; `  e9 e* _
  15.   color_t color_number = color_num;
    ' s- X: q& G" i) h  K
  16.   printf ("color1: %d\n", color1);
      _, I  M5 s0 ^( `/ s* U. N9 y
  17.   printf ("color2: %d\n", color2);
    : d% ]$ f! o# u7 |
  18.   printf ("color num: %d\n", color_number);
    ; O0 m8 B. L  E
  19.   return 0;
    ) X8 N& C5 R7 b4 [3 L& `" N
  20. }
复制代码
; V! s( h" R' x- j# V" z( `
* w2 K6 @  u7 \
枚举与typedef的结合使用方法跟结构体类似:可以使用typedef给枚举类型color声明一个新名称color_t,然后使用这个类型就可以直接定义一个枚举变量。

2 W, \7 @$ x2 m- O3 d' N3 a
2. 使用typedef的优势
不同的项目,有不同的代码风格,也有不同的代码“癖好”。看得代码多了,你会发现:有的代码喜欢用宏,有的代码喜欢使用typedef。那么,使用typedef到底有哪些好处呢?为什么很多人喜欢用它呢?
2.1 可以让代码更加清晰简洁; i- I! E3 G: f3 W7 \

  1. # R& N2 J9 N2 _
  2. typedef struct student
    # a* k7 u  ~2 O: A& l7 g0 _5 a
  3. {( d* N7 E; d- [( y" o* C
  4.   char name[20];
    ) E5 T# g6 V2 @" t6 k. u
  5.   int  age;. A6 c' h5 W4 D( S3 e
  6.   float score;9 G# T& m  O* @( X: l, K" G6 z
  7. }student_t, *student_ptr;
    7 w' z! b& A2 x/ V2 e) Q8 N, M

  8. 9 k- U, s5 @# t  O$ E0 R
  9. student_t   stu = {"wit", 20, 99};& J; e& h1 d7 q3 {& H, l. V6 ^
  10. student_t  *p1 = &stu;
    3 e+ s  f6 E# U! J/ f
  11. student_ptr p2 = &stu;
复制代码
* v6 H7 }% e% I6 r
& P3 l! f/ W0 d* R. k
如示例代码所示,使用typedef,我们可以在定义一个结构体、联合、枚举变量时,省去关键字struct,让代码更加简洁。
2.2 增加代码的可移植性
C语言的int类型,我们知道,在不同的编译器和平台下,所分配的存储字长不一样:可能是2个字节,可能是4个字节,也有可能是8个字节。如果我们在代码中想定义一个固定长度的数据类型,此时使用int,在不同的平台环境下运行可能会出现问题。为了应付各种不同“脾气”的编译器,最好的办法就是使用自定义数据类型,而不是使用C语言的内置类型。

  1. 7 e% s5 e. Z+ N. v& n+ z
  2. #ifdef PIC_16
    $ j& v5 z( A( s* s( M
  3. typedef  unsigned long U32
    : Y; L$ x) x% a
  4. #else
    9 @. V2 {/ ?5 F
  5. typedef unsigned int U32  2 C" d- p7 |1 ]  O, D! q* _4 S
  6. #endif
复制代码
$ B2 N3 q& h4 k
在16位的 PIC 单片机中,int一般占2个字节,long占4个字节,而在32位的ARM环境下,int和long一般都是占4个字节。如果我们在代码中想使用一个32位的固定长度的无符号类型,可以使用上面方式声明一个U32的数据类型,在代码中你可以放心大胆地使用U32。将代码移植到不同的平台时,直接修改这个声明就可以了。
在Linux内核、驱动、BSP 等跟底层架构平台密切相关的源码中,我们会经常看到这样的数据类型,如size_t、U8、U16、U32。在一些网络协议、网卡驱动等对字节宽度、大小端比较关注的地方,也会经常看到typedef使用得很频繁。
2.3 比宏定义更好用
C语言的预处理指令#define用来定义一个宏,而typedef则用来声明一种类型的别名。typedef跟宏相比,不仅仅是简单的字符串替换,可以使用该类型同时定义多个同类型对象。
  1. - s# m, ~; y. P7 g% _8 y8 ~& u
  2. typedef char* PCHAR1;- J  ^8 e& t2 |1 q! G' J
  3. #define PCHAR2 char *
    4 L% s# Y+ Y5 v' N
  4. ) [% k6 N# r* y+ A) J" z
  5. int main (void)
    6 @% p$ O: N. n3 F. l& O
  6. {( ~8 Q2 y3 ]& m
  7.   PCHAR1 pch1, pch2;8 D8 z0 O$ \8 z1 \
  8.   PCHAR2 pch3, pch4;  Z8 f! Q0 Q+ `
  9.   printf ("sizeof pch1: %d\n", sizeof(pch1));6 O. i) A* ?9 C* D7 F
  10.   printf ("sizeof pch2: %d\n", sizeof(pch2));
    # i6 y! c( Q, i: ^( x8 J7 K
  11.   printf ("sizeof pch3: %d\n", sizeof(pch3));
    ( j. t, _" j: r; k) q$ W
  12.   printf ("sizeof pch4: %d\n", sizeof(pch4));
    ! t9 r$ |6 C5 A( R/ v5 N0 v
  13.   return 0;
    , \' }2 r7 Q' X; A- e) v) [
  14. }
复制代码
( [* U. F; C- o3 K/ g% k
在上面的示例代码中,我们想定义4个指向char类型的指针变量,然而运行结果却是:
  1.   U' g$ V) `' I$ Q, X, [+ p
  2. sizeof pch1: 4
    . t" E$ Y  z6 k2 Z4 x3 a; Q- C9 J$ a
  3. sizeof pch2: 4$ H' G5 h% u/ D3 Z
  4. sizeof pch3: 4( D& p& M; R  |( H& t
  5. sizeof pch4: 1
复制代码

8 w* n9 x- L% c
本来我们想定义4个指向char类型的指针,但是 pch4 经过预处理宏展开后,就变成成了一个字符型变量,而不是一个指针变量。而 PCHAR1 作为一种数据类型,在语法上其实就等价于相同类型的类型说明符关键字,因此可以在一行代码中同时定义多个变量。上面的代码其实就等价于:

  1. ( Y  c3 ?( V8 o. p3 W2 \
  2. char *pch1, *pch2;- Y, D0 D7 a! @0 t
  3. char *pch3, pch4;
    " k$ b: e7 {& A+ e
复制代码
2.4 让复杂的指针声明更加简洁
一些复杂的指针声明,如:函数指针、数组指针、指针数组的声明,往往很复杂,可读性差。比如下面函数指针数组的定义:

  1. ) g1 X3 n# c3 Q, Z9 G
  2. int *(*array[10])(int *p, int len, char name[]);
复制代码
5 {) \5 Y. @0 {8 L1 |+ C& F& z6 r9 a
上面的指针数组定义,很多人一瞅估计就懵逼了。我们可以使用typedef优化一下:先声明一个函数指针类型func_ptr_t,接着再定义一个数组,就会更加清晰简洁,可读性就增加了不少:
  1. ; \) e. Z3 D8 p/ @3 z# J3 ]
  2. typedef int *(*func_ptr_t)(int *p, int len, char name[]);
    . F, z* a( `, u* H6 ?( F
  3. func_ptr_t array[10];
复制代码

6 W2 x" V: F% Z9 N* g
3. 使用typedef需要注意的地方
通过上面的示例代码,我们可以看到,使用typedef可以让我们的代码更加简洁、可读性更强一些。但是typedef也有很多坑,稍微不注意就可能翻车。下面分享一些使用typedef需要注意的一些细节。
3.1 typedef在语法上等价于关键字
我们使用typedef给已知的类型声明一个别名,其在语法上其实就等价于该类型的类型说明符关键字,而不是像宏一样,仅仅是简单的字符串替换。举一个例子大家就明白了,比如const和类型的混合使用:当const和常见的类型(如:int、char) 一同修饰一个变量时,const和类型的位置可以互换。但是如果类型为指针,则const和指针类型不能互换,否则其修饰的变量类型就发生了变化,如常见的指针常量和常量指针:

  1. 2 L9 `9 M: z* _8 ?& o
  2. char b = 10;
    ! D; q2 G( F6 }  ]. A
  3. char c = 20;
    3 J. P/ ~4 C! y0 u# S
  4. int main (void)
    9 D" s& E6 A$ l  y, H
  5. {  : ^' _% H% Q# Z5 ^
  6.   char const *p1 = &b; //常量指针:*p1不可变,p1可变
    1 P$ M; }# [/ i, Z; s
  7.   char *const p2 = &b; //指针常量:*p2可变,p2不可变  
    7 L3 s, _2 Q  H# z2 [  I$ ~
  8.   p1  = &c; //编译正常
    4 ~! N. i- M7 B
  9.   *p1 = 20; //error: assignment of read-only location  - ?  t. y- K. R) ^! k2 ^( L
  10.   p2  = &c; //error: assignment of read-only variable`p2'8 @3 a7 y& W% ^7 E( ?
  11.   *p2 = 20; //编译正常* X% |) R7 E; M' _0 _8 E
  12.   return 0;0 y+ ^! t/ C% K4 k" u( t
  13. }
复制代码

/ ?% y. I( [$ W
当typedef 和 const一起去修饰一个指针类型时,与宏定义的指针类型进行比较:

  1. : s, s5 c' V7 j' S7 j
  2. typedef char* PCHAR2;
    ) R$ @( \  g* _) N: B# b
  3. #define PCHAR1 char * 4 k8 N2 U6 h& i9 h$ A
  4. char b = 10;
    9 v8 ~. r- H* p6 _7 u7 Q  X" [8 e
  5. char c = 20;( i1 L- v" ]; c( Z7 m8 R
  6. int main (void)  J7 S+ B8 L) V0 [, j; _
  7. {  
    5 u% b7 C0 S9 C9 Q9 q
  8.   const PCHAR1 p1 = &b;
    6 J6 U& F: b, B. Q. Y
  9.   const PCHAR2 p2 = &b;+ ~" r7 _2 m) n
  10.   p1  = &c; //编译正常 9 D6 R  \/ S! |' |% o9 t4 ]; U
  11.   *p1 = 20; //error: assignment of read-only location  / V; X& }7 n' _1 z% r7 d  e: \
  12.   p2  = &c; //error: assignment of read-only variable`p2'
    8 v* ^. c3 T( O
  13.   *p2 = 20; //编译正常! s: X0 h7 P, G# }! D" u" _: H  N
  14.   return 0;! q; L/ Q5 D: V6 E$ j6 r: E
  15. }
复制代码

1 B3 C! t, M# k! Y0 D6 A
运行程序,你会发现跟上面的示例代码遇到相同的编译错误,原因在于宏展开仅仅是简单的字符串替换:

  1. : Y; j# I7 X' r! n+ Z: I$ O  X
  2. const PCHAR1 p1 = &b; //宏展开后是一个常量指针3 t% d* P6 D. G/ J5 p
  3. const char * p1 = &b; //其中const与类型char的位置可以互换
复制代码

0 X" P' ]7 y% S
而在使用PCHAR2定义的变量p2中,PCHAR2作为一个类型,位置可与const互换,const修饰的是指针变量p2的值,p2的值不能改变,是一个指针常量,但是*p2的值可以改变。

  1. . [$ [( K" w5 S; j* g( A
  2. const PCHAR2 p2 = &b; //PCHAR2此时作为一个类型,与const可互换位置. d, k1 G+ R; o/ `
  3. PCHAR2 const p2 = &b; //该语句等价于上条语句$ r) i1 U. D% F1 K( ~! e
  4. char * const p2 = &b; //const和PCHAR2一同修饰变量p2,const修饰的是p2!
复制代码

( Y3 R3 w9 X3 o
3.2 typedef是一个存储类关键字
没想到吧,typedef在语法上是一个存储类关键字!跟常见的存储类关键字(如:auto、register、static、extern)一样,在修饰一个变量时,不能同时使用一个以上的存储类关键字,否则编译会报错:
  1. , ]& \+ `7 h8 N1 Y
  2. typedef static char * PCHAR;
    # D3 A& @. |7 K
  3. //error: multiple storage classes in declaration of `PCHAR'
复制代码

6 m. u4 u- l# I" C4 w
3.3 typedef 的作用域
跟宏的全局性相比,typedef作为一个存储类关键字,是有作用域的。使用typedef声明的类型跟普通变量一样遵循作用域规则:包括代码块作用域、文件作用域等。
  1. 6 p1 u: B6 Z% j6 M$ I
  2. typedef char CHAR;
    5 T/ {: g, M. v6 e- ?( e
  3. - C: k- [$ ?( v5 t2 M
  4. void func (void)  K) e+ s; R/ D
  5. {5 U6 r0 C# P: N7 M1 m
  6.   #define PI 3.14/ e" ]; G' M+ W0 u
  7.   typedef short CHAR;
    % y: Z+ |0 a) P8 t+ l$ s
  8.   printf("sizeof CHAR in func: %d\n",sizeof(CHAR));
    4 B. G5 U) f# H* @
  9. }
    5 ]4 f5 E& ~: h

  10. 3 s/ i1 E! N3 _  V( ^9 V: \# R2 ^% k
  11. int main (void)
    8 U/ T4 p& }2 |" q( w" B, J
  12. {  2 e8 j9 X! f0 d8 q0 m: E& _
  13.   printf("sizeof CHAR in main: %d\n",sizeof(CHAR));' _  A$ J5 }3 S" n; z  f3 H: C
  14.   func();# R/ j% L* U7 z+ h, n
  15.   typedef int CHAR;
    $ V1 l# v7 A0 Z+ M7 I% e4 q
  16.   printf("sizeof CHAR in main: %d\n",sizeof(CHAR));
    ; K- W' _  U5 k* v0 @% x3 z
  17.   printf("PI:%f\n", PI);  / g6 T9 ]$ ]. Z  ~$ k% A
  18.   return 0;
    - e3 x6 `5 G# i- H% p1 E$ `9 s
  19. }
复制代码

. {3 L! e: V) r9 g' J4 u! d
宏定义在预处理阶段就已经替换完毕,是全局性的,只要保证引用它的地方在定义之后就可以了。而使用typedef声明的类型则跟普通变量一样遵循作用域规则。上面代码的运行结果为:
  1. 5 [/ u. E  \- s* Y
  2. sizeof CHAR in main: 1- i* F& q7 A0 u1 D' i
  3. sizeof CHAR in func: 2
    ! j& p% i( P) V2 k' R  x
  4. sizeof CHAR in main: 4
    2 p5 g$ x" ~) M! D7 c% @: e9 L
  5. PI:3.140000
复制代码

9 o" |* M% K- U" X" H, {& _( r# G0 k

% Y* o! v; n/ _; s6 H. L
4 如何避免typedef的滥用?
通过上面的学习我们可以看到:使用typedef可以让我们的代码更加简洁、可读性更好。在实际的编程中,越来越多的人也开始尝试使用typedef,甚至到了“过犹不及”的滥用地步:但凡遇到结构体、联合、枚举都要用个typedef封装一下,不用就显得你low、你菜、你的代码没水平。
其实typedef也有副作用,不一定非得处处都用它。比如上面我们封装的STUDENT类型,当你定义一个变量时:
  1. ) I) j; |+ a2 r, j* A& w
  2. STUDENT stu;
复制代码
- O, x# W; J5 g/ I* b7 L
不看STUDENT的声明,你知道stu的含义吗?未必吧。而如果我们直接使用struct定义一个变量,则会更加清晰,让你一下子就知道stu是个结构体类型的变量:
  1. 7 n: |7 |7 ?5 f6 ^4 B0 e( i
  2. struct  student stu;
复制代码

, M: \9 Z4 U( @
一般来讲,当遇到以下情形时,使用typedef可能会有用,否则可能会适得其反:
  • 创建一个新的数据类型
  • 跨平台、指定长度的类型:如U32/U16/U8
  • 跟操作系统、BSP、网络字宽相关的数据类型:如size_t、pid_t等
  • 不透明的数据类型:需要隐藏结构体细节,只能通过函数接口访问的数据类型

    6 i" O& G* b- b' r: v
在阅读Linux内核源码过程中,你会发现大量使用了typedef,哪怕是简单的int、long都使用了typedef。这是因为:Linux内核源码发展到今天,已经支持了太多的平台和CPU架构,为了保证数据的跨平台性和可移植性,所以很多时候不得已使用了typedef,对一些数据指定固定长度:如U8/U16/U32等。但是内核也不是到处到滥用,什么时候该用,什么不该用,也是有一定的规则要遵循的,具体大家可以看kernel Document中的 CodingStyle 中关于typedef的使用建议。

6 A3 {8 K3 G$ Q0 g9 F
赞 收藏 评论1 发布时间:2020-5-11 19:41

举报

1个回答
goyhuan 回答时间:2020-5-12 09:48:25
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版