嵌入式C进阶一 —— 关键字(2)

  上一篇文章提到了C语言中的关键字,主要介绍了基础数据类型和修饰符的关键自己,这一篇主要记录一下对于数据结构方面的几个关键字。

struct

  struct即是我们所说的结构体。他将一些相关联的数据打包成一个整体,方便使用。

  其实它的概念通俗的来说,就像OOP语言中的类一样,只不过我们的结构体里没有函数,只有各种“属性”或者“字段”。(PS:C语言中只能包含数据,C++中可以包含成员函数,和class更加相似,C语言中也可以实现类似成员函数的方式,利用函数指针可以做到像OOP一样类似的封装) 

  说到结构体,最折磨人的就是它的大小问题。 普通结构体的大小涉及到内存对齐,位域访问的问题,这个部分内存对齐的只是将在另一边文章中整理,首先我们先看一下空结构的大小问题,大小是0吗? 很遗憾,大小是1。

  如果定义一个空结构体,把它看成一个模子,模子当然不能为0。编译器认为任何一种数据类型都有其大小,同样它也认为任何一个结构体都是有大小的,哪怕它是空的。

union

  关键字union,即联合体。它和struct非常相像,但是含义却有较大的差别。

  我们知道,struct结构体的大小是考虑到其中每个成员后,经过内存对齐(内存对齐主要是优化,为了更快的访问)而产生的。而union则只是维护足够的空间(即成员中大小最大的数据类型)来放置多个数据成员的一种,而并非给每个成员都配置空间。

  所有的成员都有相同的起始地址。一个形象的比喻:struct就像是一个大别墅,每个成员都有自己的房子,大家都在里面住也没任何问题;而union就比较可怜了,只有一个房间,大小够成员中最胖的那个住进去,但是就像是多维空间,我们从不同的维度(类型或成员)看上去会看到不同的成员。 

  union主要的用处就是压缩空间。如果一些数据不可能在同一时间被用到,则他们可以写进同一个union里面。 另外一个用法就是用它来做一些数据结构的解析,比如数组到int的转换:

union CONVERT
{
    int data[2];
    char byte[8];
}Convert;

  如果将通信中的数据流拷贝到Convert.byte数组中,通过读取Convert.data就可以得到int类型的数据。

enum

枚举类型一般它的定义如下:

enum enum_type_name
{    
    ENUM_CONST_1,    
    ENUM_CONST_2,    
    ......    
    ENUM_CONST_n
}enum_variable_name; 

  其中里面的例如ENUM_CONST_1就是我们常说的枚举常量。

  需要注意的一点是,enum中的常量可以赋值,但是如果你不给它赋值则会从被赋了初值的那个常量开始依次加1.如果没有给赋任何值,则从第一个值开始自动赋0,往后每个变量都自增1.

  至于enum的大小,你在使用它的时候它的类型就已经确定了,这时大小你自己心里也就有数了。enum可以一次定义大量相关的常量,而且使用方便。

typedef

  typedef关键字有许多人对这个关键字的认知是:定义一个“新的”数据类型。但是它的真正作用是:给一个已经存在的数据类型(注意,不是变量)取一个别名。

  它的主要用处就是,取了别名之后我们可以更清楚的一眼看懂这个数据类型的含义,另一方面我们还可以自定义类型来做到平台兼容和系统移植。常见的使用场合就是结构体定义的时候。

typedef struct Student
{    
    //code..
}stu,*stu_p;

  此时结构体Student 就有了别名stu,即

  • struct Student stu1 等价于 stu stu1;
  • struct Student* stu2 等价于 stu_p stu2 等价于 stu * stu2;

  现在我们顺便回顾一下以前的知识:

const stu_p stu3;
stu_p const stu4;

这两句的const分别修饰的是谁呢?

  答案是stu3和stu4。因为我们说了typedef的含义是,给"数据类型"起一个别名。所以stu_p不单单是一个指针,而是一个数据类型。const在判断时会自动忽略数据类型,所以自然它也就被当作不存在啦。

You may also like...

发表评论

电子邮件地址不会被公开。