电子产业一站式赋能平台

PCB联盟网

搜索
查看: 137|回复: 0
收起左侧

嵌入式 C 语言,typedef 的妙用和滥用。

[复制链接]

568

主题

568

帖子

4221

积分

四级会员

Rank: 4

积分
4221
发表于 2025-1-27 08:01:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师3 ?6 b! \% s) j5 S  j; A% t
关注我,一起变得更加优秀!摘要:不同的项目,有不同的代码风格,也有不同的代码“癖好”。看得代码多了,你会发现:有的代码喜欢用宏,有的代码喜欢使用typedef。那么,使用typedef到底有哪些好处呢?为什么很多人喜欢用它呢?/ ?6 _5 s% D5 ^9 C# F; K/ O+ n' i
1. typedef 的基本使用1.1 typedef与结构体的结合使用typedef是C语言的一个关键字,用来给某个类型起个别名,也就是给C语言中已经存在的一个类型起一个新名字。大家在阅读代码的过程中,会经常见到 typedef 与结构体、联合体、枚举、函数指针声明结合使用。比如下面结构体类型的声明和使用:
/ U; j# A1 b3 g* b0 |struct student5 c) [7 v! S7 L" [
{
" h0 H) B7 v1 ~) {: U8 @' j+ k# R  char name[20];
3 {4 u; s. u( c% C+ K9 t; S2 u  int  age;4 \1 J5 s  F4 Y3 \" Z
  float score;& I" R1 P3 N0 D0 k# z; D! ~' M+ J
};
2 t7 _( ?, @# [struct student stu = {"wit", 20, 99};1 ^* M; K: m" r  N# C9 |+ `, b
在C语言中定义一个结构体变量,我们通常的写法是:
2 p& @  i' c7 i' Fstruct 结构体名 变量名;
( ^) l1 `& H* y  d) B: b前面必须有一个struct关键字打前缀,编译器才会理解你要定义的对象是一个结构体变量。而在C++语言中,则不需要这么做,直接使用:结构体名 变量名就可以了$ C2 c; {) O0 H' ]
struct student * @5 n$ w8 V% G" j% M$ E
{( Y' J8 d: I9 W7 @- R# B5 {1 k
  char name[20];1 I) G& ]( ?$ O( {5 {0 N
  int age;, E8 X2 w8 d- m
  float score;
% f! w; T! Y" [% e! c3 J8 B};" `7 ?2 {6 Q4 d% U" q0 G1 U6 Z* d0 ~6 P
int main (void); g3 K" A6 Y( b5 k% W
{0 ~5 y# q/ |+ Y; G
  student stu = {"wit", 20, 99};) p/ J( N) k6 R! r5 [% Z1 c
  return 0;
4 o& ^: Q2 `' _( V}8 i5 y; y/ o7 W3 h. n/ S3 E
如果我们使用typedef,就可以给student声明一个别名student_t和一个结构体指针类型student_ptr,然后就可以直接使用student_t类型去定义一个结构体变量,不用再写struct,这样会显得代码更加简洁。
& V3 S; K( ~, Y6 X#include
* r3 l; A5 l% U! U# R0 L/ ztypedef struct student$ U+ \4 W+ V5 H1 ]% V0 p/ F
{
9 p! u0 B+ H& o; s  Q4 q, F  char name[20];
5 y5 c& j+ ], Z" E- n+ u  int  age;
: A6 ~2 y& ^5 s9 B) S9 b( o' T  float score;
# P5 X; X. T6 V& E: v; Q, s}student_t, *student_ptr;7 \- m2 E& @9 {% j& Y& B9 E
int main (void)
$ G* K. f# p( X; b! E{0 n& E( m  G; l
  student_t   stu = {"wit", 20, 99};
& t+ M8 ]' b, a9 b: l9 X  student_t  *p1 = &stu;
( S& }% x( j) m! [  student_ptr p2 = &stu;
& m" ^2 h( b+ Q6 j  printf ("name: %s
% |6 C$ ?' N. W1 ?", p1->name);. E7 R4 n- Z$ H7 V9 n
  printf ("name: %s
! p1 n* a# F# Y: M", p2->name); 1 @( }( V: Q! h. G" L
  return 0;
1 f7 T% \9 K. ~% X0 O}
; Y4 N3 n/ S- \; `+ x: ^程序运行结果:& {2 N  P. Z# a* k8 z  `4 P
wit
7 ]% I$ @0 B+ ~( K$ e; u: wwit
. Z8 ?; @. {) y; A. J' l2 N1 l1. 2 typedef 与数组的结合使用typedef除了与结构体结合使用外,还可以与数组结合使用。定义一个数组,通常我们使用int array[10];即可。我们也可以使用typedef先声明一个数组类型,然后再使用这个类型去定义一个数组。
5 `- i5 Y4 v; }, T0 `4 x- G. P, E. |typedef int array_t[10]; 3 w/ G3 F) b: {: D. |& e) E
array_t array;
1 i# }0 }! I, e+ W, Vint main (void)) g$ c6 `) r2 n5 ^- |6 Y4 |* ^
{# V8 b9 ^, d+ ?. D
  array[9] = 100;  y  f* q% r9 ?( m+ m
  printf ("array[9] = %d
! T& _6 y. z, G' y7 N8 k) b9 A", array[9]);9 E( g2 S0 d" ^( t* I! v' @
  return 0;
* `2 a' R' T0 V4 Q( f5 [; w- i8 v}" Y) _" Y) B6 E. Z  F2 M, e- m. h
在上面的demo程序中,我们声明了一个数组类型array_t,然后再使用该类型定义一个数组array,这个array效果其实就相当于:int array[10]。
+ I' S: ^  g. Z. X2 @; A1.3 typedef 与指针的结合使用
9 O  G6 d& o5 C% Mtypedef char * PCHAR;; ^5 C- V; q! J3 ^5 o' n
int main (void)
% _3 m9 e. j  ~2 r{) F* W8 C  o5 j
    //char * str = "学嵌入式";+ g5 L0 E; J: j0 {# U
  PCHAR str = "学嵌入式";  i2 e. U, E9 o" J* t% l  `) x
  printf ("str: %s! C& f& g% N$ t& }( c3 m
", str);
: x4 P; ^- L/ O4 ~& U  return 0;
5 k, U; Y9 e+ M9 S6 Q% Q0 F}) Z( X1 N6 Q. s. \2 R) ~6 j' w4 A
在上面的demo程序中,PCHAR 的类型是char *,我们使用PCHAR类型去定义一个变量str,其实就是一个char *类型的指针。* O! m+ N' l& D/ H
1.4 typedef与函数指针的结合使用定义一个函数指针,我们通常采用下面的形式:5 `3 I' N- W9 x  t
int (*func)(int a, int b);
# e3 _; W6 @0 C) |/ d6 ]% o- \6 ?我们同样可以使用typedef声明一个函数指针类型:func_t. B7 x; |% m3 @/ l/ M
typedef int (*func_t)(int a, int b);
( _$ g' O# S% ]7 ?7 E% N; r7 e. _; Wfunc_t fp;  // 定义一个函数指针变量8 E9 }- b. Z' C- [: I
写个简单的程序测试一下,运行OK:$ Y( g; {2 [2 c# Y& N+ z3 [
typedef int (*func_t)(int a, int b);8 V) w& K9 Q/ L/ G
int sum (int a, int b)5 t7 Q3 \( v  g" T
{  Y& m( k8 x: i3 t
  return a + b;1 t7 `( g; R/ F
}
! y: A: I  s8 j: p( C2 D' B0 m" z2 Qint main (void)
! Q9 U: {( C3 n0 ~7 ^% N{0 L" ~3 Y/ S9 B
  func_t fp = sum;# Y5 i- T- C4 x/ J- T/ ~
  printf ("%d/ F* j4 s% Z) q+ m7 S6 Z# K/ x5 D$ k
", fp(1,2));
: T% G, J1 [4 ~  i9 f  return 0;
' L* Q( Q6 L, \% ~$ E: l# b: `}# b9 N* }4 m+ C) W4 V+ ^9 h. Z
为了增加程序的可读性,我们经常在代码中看到下面的声明形式:* W# X7 u8 H# g; o  H0 D
typedef int (func_t)(int a, int b);' W$ y/ X9 g$ [. Z% d* j5 h# s- I
func_t *fp = sum;
* j6 }8 M) ~& o3 P/ {5 T8 Z7 k函数都是有类型的,我们使用typedef给函数类型声明一个新名称:func_t。这样声明的好处是:即使你没有看到func_t的定义,也能够清楚地知道fp是一个函数指针,代码的可读性比上面的好。, F" {3 o& W  Z4 r1 m. M
1.5 typedef与枚举的结合使用typedef enum color
* |6 _2 M3 \8 F5 I{" m3 l# ]6 l% K( ]  X% H. A
  red,
8 F0 i: E+ [: f1 w! Z- [2 d9 ]  white,
0 Y1 V: U  b1 G5 e  black,
- @5 Q9 q( U" o- }  green,, }7 U* l; k9 F" {- I- {
  color_num,( d' N3 e6 ?, k) E- B: l! S
} color_t;4 n- m& o, P' k% T, C; g9 I
int main (void)1 s0 G  G  T: K. J% a: }
{
- @+ r5 K( Z3 U5 w6 l3 w* @  enum color color1 = red;
9 M+ T5 _' h+ H  U( c) l  color_t    color2 = red;( o* ?$ H' D* M9 `7 c6 U
  color_t color_number = color_num;
9 E: x5 i/ a/ N1 I  printf ("color1: %d
4 w; Q( Y  P. F& P( J9 W. B", color1);
8 V. U/ {% H+ G  printf ("color2: %d* M  @, @" l+ ?3 c* n6 Y: }
", color2);! r! i: E: S( f
  printf ("color num: %d
" Q. U* v1 d- t", color_number);
: \  Y$ u, l% w6 ]1 }! M# G. A  return 0;
0 S1 w! q* F) d( D}
' d$ |$ d! J& Q& k! a枚举与typedef的结合使用方法跟结构体类似:可以使用typedef给枚举类型color声明一个新名称color_t,然后使用这个类型就可以直接定义一个枚举变量。* l# r2 `; d  F1 ~) n, ^; X
2. 使用typedef的优势不同的项目,有不同的代码风格,也有不同的代码“癖好”。看得代码多了,你会发现:有的代码喜欢用宏,有的代码喜欢使用typedef。那么,使用typedef到底有哪些好处呢?为什么很多人喜欢用它呢?
4 s- T9 m4 K7 {5 G) K5 X/ [* e2.1 可以让代码更加清晰简洁typedef struct student/ t5 Y7 u; x1 g& r+ [2 ]
{/ X* }, L9 j- s% |5 H: C6 ]
  char name[20];
" g; q, N! P" B7 R: x5 A  int  age;
- o8 U* v8 F3 X" |& q9 L5 U  float score;
  r& A. P8 v' `$ E$ L( m( {}student_t, *student_ptr;
$ {5 O) |' D7 h4 u% F+ _, Q9 nstudent_t   stu = {"wit", 20, 99};9 k, [# _) l/ w( B8 @( O! n6 E
student_t  *p1 = &stu;
" U: k& I3 c* t4 u6 I: U. Astudent_ptr p2 = &stu;
* D, V6 a3 `4 ^4 E如示例代码所示,使用typedef,我们可以在定义一个结构体、联合、枚举变量时,省去关键字struct,让代码更加简洁。/ R* M" q% u# h
2.2 增加代码的可移植性C语言的int类型,我们知道,在不同的编译器和平台下,所分配的存储字长不一样:可能是2个字节,可能是4个字节,也有可能是8个字节。如果我们在代码中想定义一个固定长度的数据类型,此时使用int,在不同的平台环境下运行可能会出现问题。为了应付各种不同“脾气”的编译器,最好的办法就是使用自定义数据类型,而不是使用C语言的内置类型。! L( j% x, q. e' j  P! ~
#ifdef PIC_16" U$ a' }' B" y5 ?' a
typedef  unsigned long U32
* s5 {& Q$ b: w; b#else) K/ T: ~2 B; ?9 c
typedef unsigned int U32  ! d: I5 c4 q/ s# d! H
#endif# \  c8 ~/ G/ e* s. R" O8 t4 L2 F; _
在16位的 PIC 单片机中,int一般占2个字节,long占4个字节,而在32位的ARM环境下,int和long一般都是占4个字节。如果我们在代码中想使用一个32位的固定长度的无符号类型,可以使用上面方式声明一个U32的数据类型,在代码中你可以放心大胆地使用U32。将代码移植到不同的平台时,直接修改这个声明就可以了。1 m. {! @; h* B# Q: h
在Linux内核、驱动、BSP 等跟底层架构平台密切相关的源码中,我们会经常看到这样的数据类型,如size_t、U8、U16、U32。在一些网络协议、网卡驱动等对字节宽度、大小端比较关注的地方,也会经常看到typedef使用得很频繁。! c: J( t" a/ [$ k% H
/ |6 u8 Z+ K6 J5 h2 I2 }3 m
2.3 比宏定义更好用C语言的预处理指令#define用来定义一个宏,而typedef则用来声明一种类型的别名。typedef跟宏相比,不仅仅是简单的字符串替换,可以使用该类型同时定义多个同类型对象。
3 x2 z  m% D& M4 L; p% ~2 X8 ltypedef char* PCHAR1;4 l/ E$ ~: f+ S) \
#define PCHAR2 char *) w% z; C  c& x# I) l- S
int main (void)
7 i; i" Z8 q! l+ N7 ]5 ~  B{5 A" ?* e1 c' A. s3 p  f/ Y" x
  PCHAR1 pch1, pch2;* a5 F0 M* p9 K% `
  PCHAR2 pch3, pch4;
# Y% \; _3 `6 D2 M* h0 `) w  printf ("sizeof pch1: %d" h" f4 |, L5 A, x9 j1 W; e1 [
", sizeof(pch1));7 D3 s+ X- Q" t, r% [% Z
  printf ("sizeof pch2: %d
+ \: R8 {. q) a  N7 P4 |", sizeof(pch2));5 W4 f4 |" C" r; T
  printf ("sizeof pch3: %d
8 r  h  H0 ^+ {! H0 G; n7 W", sizeof(pch3));
$ p$ I- r' t3 R  Y! }& O  printf ("sizeof pch4: %d
  W% u5 j  @# j", sizeof(pch4));# {7 q/ D! ?* o3 m3 B7 V9 k
  return 0;
8 {3 @5 \0 z* y  g" Y& ?8 b}8 A0 W0 C% }5 o$ r) W3 G! N3 D
在上面的示例代码中,我们想定义4个指向char类型的指针变量,然而运行结果却是:
* q1 r* [: `0 usizeof pch1: 44 i: p/ q% r, m$ f; ]( P  {
sizeof pch2: 4: `* {/ A* N* P6 ~* J
sizeof pch3: 4
& W' K" m: k9 o2 {3 c9 W& j& Msizeof pch4: 1
; A! W9 S7 ]! r1 T, A  [2 [; Q4 r# O& C本来我们想定义4个指向char类型的指针,但是 pch4 经过预处理宏展开后,就变成成了一个字符型变量,而不是一个指针变量。而 PCHAR1 作为一种数据类型,在语法上其实就等价于相同类型的类型说明符关键字,因此可以在一行代码中同时定义多个变量。上面的代码其实就等价于:
% a) E' C/ Z7 ]0 {3 Pchar *pch1, *pch2;2 \; O( f7 g4 p0 j4 ?9 P3 D
char *pch3, pch4;
" {' I! u% @7 {2.4 让复杂的指针声明更加简洁一些复杂的指针声明,如:函数指针、数组指针、指针数组的声明,往往很复杂,可读性差。比如下面函数指针数组的定义:4 K9 h$ q8 i; A0 n/ C
int *(*array[10])(int *p, int len, char name[]);# V( u. H" L4 ?% s1 ~1 h
上面的指针数组定义,很多人一瞅估计就懵逼了。我们可以使用typedef优化一下:先声明一个函数指针类型func_ptr_t,接着再定义一个数组,就会更加清晰简洁,可读性就增加了不少:; g3 O( p- F% E& ~* Z) y
typedef int *(*func_ptr_t)(int *p, int len, char name[]);" }$ u8 d) k- D% Y
func_ptr_t array[10];
8 Y; b+ d# @; D3. 使用typedef需要注意的地方通过上面的示例代码,我们可以看到,使用typedef可以让我们的代码更加简洁、可读性更强一些。但是typedef也有很多坑,稍微不注意就可能翻车。下面分享一些使用typedef需要注意的一些细节。: c9 W) o4 z3 ?9 s
3.1 typedef在语法上等价于关键字我们使用typedef给已知的类型声明一个别名,其在语法上其实就等价于该类型的类型说明符关键字,而不是像宏一样,仅仅是简单的字符串替换。举一个例子大家就明白了,比如const和类型的混合使用:当const和常见的类型(如:int、char) 一同修饰一个变量时,const和类型的位置可以互换。但是如果类型为指针,则const和指针类型不能互换,否则其修饰的变量类型就发生了变化,如常见的指针常量和常量指针:+ ?8 ]6 y4 b6 O' B
char b = 10;( z4 m0 f7 B5 I2 E3 ~
char c = 20;
" _- Y3 T, \) `) {int main (void)/ G2 b( N" d& E, M( O; O" o
{  
& j$ }' S7 N# h6 B* f0 c  char const *p1 = &b; //常量指针:*p1不可变,p1可变
% N2 M5 P" _# H/ c  X) E  char *const p2 = &b; //指针常量:*p2可变,p2不可变  ! P& M% `* V4 p3 ~6 a! c, p1 s
  p1  = &c; //编译正常 & ^0 p- `" a! t  G: |
  *p1 = 20; //error: assignment of read-only location  
# h1 S9 x, ^9 \8 `' I$ T9 v+ J  p2  = &c; //error: assignment of read-only variable`p2'
  B- v+ p* I2 O$ g  *p2 = 20; //编译正常
/ j$ c( `# p; j4 t) d& Z  return 0;- P' I' D; w3 E+ |  i/ o, [9 R* J
}5 P& e$ M4 T: T; q
当typedef 和 const一起去修饰一个指针类型时,与宏定义的指针类型进行比较:
. m$ D' w" j3 b. j0 ptypedef char* PCHAR2;
( \# C4 m1 c* [9 o#define PCHAR1 char * 5 @" k0 k& m; H3 y5 u& h" L
char b = 10;
9 ]" m1 C0 ~; A$ A  @char c = 20;  B; z; W# Z. @0 s4 R% D( @/ r  C
int main (void)
+ s; c/ v! [8 t/ B, n{  / m* G2 U' ?5 r+ I& U4 P6 [7 C
  const PCHAR1 p1 = &b;) r4 Z+ A5 w- u1 W- ]9 o
  const PCHAR2 p2 = &b;( s+ V6 Q6 n! }9 l' [" f+ \4 F1 c* ]1 z
  p1  = &c; //编译正常
, N0 K2 z1 r% t, S& F. E3 d  *p1 = 20; //error: assignment of read-only location  
) w' k( k2 g8 x2 |# d  p2  = &c; //error: assignment of read-only variable`p2'
, q" U# T0 N. i' f  *p2 = 20; //编译正常- x% @7 b& o* J6 ?1 }8 o4 h
  return 0;. K  R# W/ J. D+ b0 c% _0 A
}
8 }2 S4 t& u+ G. T/ g3 v运行程序,你会发现跟上面的示例代码遇到相同的编译错误,原因在于宏展开仅仅是简单的字符串替换:
2 w8 [# }/ W* Y. m! D7 ]$ u8 ^& K4 hconst PCHAR1 p1 = &b; //宏展开后是一个常量指针
% }+ @5 f9 C9 _% Kconst char * p1 = &b; //其中const与类型char的位置可以互换: E# C5 i- \' d- F2 j6 B
而在使用PCHAR2定义的变量p2中,PCHAR2作为一个类型,位置可与const互换,const修饰的是指针变量p2的值,p2的值不能改变,是一个指针常量,但是*p2的值可以改变。
7 G7 r7 T0 ^" O& r+ ?2 E$ Cconst PCHAR2 p2 = &b; //PCHAR2此时作为一个类型,与const可互换位置
' K; p, p% `" fPCHAR2 const p2 = &b; //该语句等价于上条语句' c5 z2 O3 E* Q2 C
char * const p2 = &b; //const和PCHAR2一同修饰变量p2,const修饰的是p2!
, X% o* n0 m% [; O3.2 typedef是一个存储类关键字没想到吧,typedef在语法上是一个存储类关键字!跟常见的存储类关键字(如:auto、register、static、extern)一样,在修饰一个变量时,不能同时使用一个以上的存储类关键字,否则编译会报错:
0 L# n( b# S4 Z+ M2 Z/ rtypedef static char * PCHAR;5 D+ p  O* ]- k0 _$ J
//error: multiple storage classes in declaration of `PCHAR'& T- ]/ ^+ w! E' i
3.3 typedef 的作用域跟宏的全局性相比,typedef作为一个存储类关键字,是有作用域的。使用typedef声明的类型跟普通变量一样遵循作用域规则:包括代码块作用域、文件作用域等。  W3 d; |3 ^! r' [( E
typedef char CHAR;
/ |4 o% g( D  u/ |0 Mvoid func (void)6 ~! E% W3 z% y7 F
{$ ^# z+ U0 E1 a& x6 V
  #define PI 3.14+ y7 r* S7 x. R% v! H/ A/ _
  typedef short CHAR;
; a! A4 e( o1 H5 U  printf("sizeof CHAR in func: %d
/ K1 V. U3 ]9 l; G4 H/ v",sizeof(CHAR)); & F9 |2 H$ {. T- y  }
}
0 Y1 _% X! t4 Q9 H, Y; jint main (void)
% t8 a: y3 u+ o9 U* n  f2 b4 }, m{  # D+ h2 [2 Q* d3 R3 T, o- D- ^
  printf("sizeof CHAR in main: %d
& c: o* S" {. }* M" ]% ]& g: U",sizeof(CHAR));
4 |' a$ g- q+ ?/ L% b$ U  func();- x/ e, _0 G( S& }: J
  typedef int CHAR;) ]% p: g7 F5 k
  printf("sizeof CHAR in main: %d
8 E( y, @, K7 \/ _3 K6 }) {2 A; T. _" l",sizeof(CHAR));
/ Z' Z* g$ j6 p$ t6 f  printf("PI:%f
, d; m  ~4 N+ L7 k  p( t, G", PI);  
3 X' u5 I% Z  H: F  \  return 0;
2 \/ o# _: |# P0 f1 E/ Q}
% W# p( g2 F  h宏定义在预处理阶段就已经替换完毕,是全局性的,只要保证引用它的地方在定义之后就可以了。而使用typedef声明的类型则跟普通变量一样遵循作用域规则。上面代码的运行结果为:; d* V+ j1 r" T" t8 V
sizeof CHAR in main: 1/ x9 K6 q* r; v
sizeof CHAR in func: 2+ N7 X4 i+ s2 ~  k5 {
sizeof CHAR in main: 48 c9 ]- W! n. Y1 x5 `
PI:3.140000
. p% |* W8 w- @$ d3 \  F4 如何避免typedef的滥用?通过上面的学习我们可以看到:使用typedef可以让我们的代码更加简洁、可读性更好。在实际的编程中,越来越多的人也开始尝试使用typedef,甚至到了“过犹不及”的滥用地步:但凡遇到结构体、联合、枚举都要用个typedef封装一下,不用就显得你low、你菜、你的代码没水平。
; F9 S7 N) c" h# [( z8 v其实typedef也有副作用,不一定非得处处都用它。比如上面我们封装的STUDENT类型,当你定义一个变量时:
1 S! c* W& G8 M- iSTUDENT stu;
  P- w/ G) d7 t# T; Y不看STUDENT的声明,你知道stu的含义吗?未必吧。而如果我们直接使用struct定义一个变量,则会更加清晰,让你一下子就知道stu是个结构体类型的变量:
  t; W2 A! F! r) gstruct  student stu;2 F& c* b/ S* y" q" ^. m) P
一般来讲,当遇到以下情形时,使用typedef可能会有用,否则可能会适得其反:
2 _5 B( u% A" r" ^
  • 创建一个新的数据类型
  • 跨平台、指定长度的类型:如U32/U16/U8
  • 跟操作系统、BSP、网络字宽相关的数据类型:如size_t、pid_t等
  • 不透明的数据类型:需要隐藏结构体细节,只能通过函数接口访问的数据类型
    / R. Y3 S& y- ~5 `$ e
    在阅读Linux内核源码过程中,你会发现大量使用了typedef,哪怕是简单的int、long都使用了 typedef。这是因为:Linux内核源码发展到今天,已经支持了太多的平台和CPU架构,为了保证数据的跨平台性和可移植性,所以很多时候不得已使用了typedef,对一些数据指定固定长度:如U8/U16/U32等。但是内核也不是到处到滥用,什么时候该用,什么不该用,也是有一定的规则要遵循的,具体大家可以看kernel Document中的CodingStyle中关于typedef的使用建议。* S2 Z- H5 \! ^) T* n
    文章来源:网络-END-
    ; ^6 h  K& n! p( u. Y往期推荐:点击图片即可跳转阅读
    " s! M3 m3 I: m$ k5 X/ ^' `8 A# M7 O( F; q% [: _8 `
                                                            ) |' ]( O5 P6 b" S
                                                                   
    . v: g7 V) M! h4 A  L5 ^3 V                                                                       
    ; r/ `* W' H0 J& f6 A; k6 M                                                                                + q8 e5 u# g+ H3 N! p/ c2 u& y" ]

    ktxk1fuf3t3640361516.jpg

    ktxk1fuf3t3640361516.jpg
    5 ]9 S) S' g. `4 q5 m+ F( t
                                                                                   
    ( _% I. P! Q- _                                                                                        嵌入式软件,能用“低代码”的方式进行开发吗?
    ( @( k: n' l# [9 {/ X  }3 F                                                                               
      A& S& ?+ P; {7 i2 P. H" w                                                                        3 C4 ?3 T+ b8 B  S: ^9 R) x
                                                                    6 T/ D% E% T! E* L
                                                           
    " t$ ~2 \( n3 T2 T$ l/ T. n. ]                                                * q- s7 C" p" E5 k; @$ w/ N
    7 @9 n- r7 {# a2 Q3 z; X  c+ l
                                                           
    + p+ O7 g; o9 s+ Q3 J. m                                                                / U! v. }; |2 ]. m. a
                                                                           
    ' o+ W) ]  R1 y: [                                                                               
    7 o) F% `0 W% E0 W

    31wyoo5uc3v640361616.jpg

    31wyoo5uc3v640361616.jpg
    5 T5 g" j" r) d: U/ y3 F
                                                                                    ; N9 r7 ?# x- J/ L
                                                                                            很大的一个坑,稍有不注意,又是一次硬件研发失误!
    # I+ L" g+ H7 ]5 G  t, h# v                                                                               
    9 i8 N& q& j) i& }* L$ f* l! H7 l                                                                       
    & B+ V5 T1 M1 ?7 z1 g5 f4 j                                                                6 p' I) }+ R1 @, {" @; l
                                                            - ]& Y4 ^& [5 d( s& e1 p" B
                                                    - g& L7 i* i8 S2 I9 |, r
    3 D# ^& l6 j4 B3 A7 r6 S# p
                                                           
      @& Y/ y7 \$ q9 I: M" f                                                               
    . ]% o3 h1 k' `+ v: k  I8 A0 i! P& T9 K                                                                       
    + l4 {7 f  a2 \" a                                                                                & N# W; b; B! r( x

    y5qv5zkox5v640361716.jpg

    y5qv5zkox5v640361716.jpg

    8 j1 i- k/ N' O( {                                                                                # m' [: Y3 V/ R. D$ {2 x
                                                                                            嵌入式 C 语言函数的返回值,也有其应用“潜规则”?
    9 V9 q+ r  M8 e2 C) Q7 c                                                                                0 f  d5 _' R  {/ {+ v/ Z! z
                                                                           
    $ V8 V5 q/ q# G# y                                                                # Y+ p5 V0 x3 D& D& s
                                                           
    ( a: Y. D+ C; ^) H$ V                                               
    , Q# y* S1 m( O, [6 Y2 d5 s我是老温,一名热爱学习的嵌入式工程师
    . s" S9 p. f6 R3 k5 R3 n% B6 @关注我,一起变得更加优秀!
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表