结构体知识总结

  struct B{                    int a;
                               char b;
}

        关于结构体,我们一定不会陌生,结构体可以说和类的用法类似,但是也有不同之处,总的来说,结构体的使用使我们可以更加方便的存储和使用数据。我在上面就定义了一个结构体,里面有两个元素,一个是int类型的,一个是char类型的,因此,结构体里面可以放进去不同类型的数据,这跟结构体的空间开辟有很大的关系。

       结构体的空间开辟都是一整块的开辟,所以他的存储又和数组中元素存储类似,不过有一点需要区别的就是,数组中的元素都是连续存放的,结构体不是的。如果定义一个指针指向这个结构体,那么指针的地址一定和结构体的第一个元素的地址相同,但是,作为不同类型元素的共同存储空间,结构体里面的数据存放地址不是连续存放的。还是拿上面的举例子,char只占一个字节,而int占四个字节,当要访问int类型的数据的时候,地址会出现冲突,因为int类型数据都是每4个4个访问的,所以,这样做的话,必须要先访问char 类型数据的地址,然后才能通过这个地址找到int 的地址,增加了访问时间,不太推荐这种访问类型。

这里就涉及到了内存对齐

内存对齐简单点来说,就是要让结构体当中存放的数据能够顺利的一次就能访问成功,但是,相对的来说,它会牺牲一点内存空间来节省运行时间。

      下面举个栗子

struct fm
{
	char c1;
	int i;
	char c2;
}

在上面,我定义了一个结构体 fm ,里面有三个元素,两个char类型,一个int型,如果要你计算这个结构体占用的字节数,你或许会说是6,因为一个char类型的数据占一个比特位,一个int类型占4个比特位,那么加起来不就是6吗?

其实,想的是么错,但是实际上答案是12,为什么是这样呢,简单点说,结构体存在内存对齐,出现内存对齐有两个原因

  1. 不是所有的硬件平台都能任意访问任意地址上的任意数据

2.为了访问未对齐的数据,处理器需要做两次内存访问

基于这两点,软件工程师为了打破硬件的限制以及为了节省访问时间,所以就提出了内存对齐这么一个概念。

内存对齐有几条规则,只要掌握了这几条规则,那么不管是什么数据都可以计算清楚到底花费了多少内存,那我就把这几条规则写在下面吧,虽然有些跑题,不过还是让你们看看吧

扫描二维码关注公众号,回复: 1565265 查看本文章

1.第一个成员在与结构体偏移量为0的地址处

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处    vs默认为8,Linux下默认为4

3.结构体总大小为最大对齐数的整数倍

4.如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的  整数倍

       好了,关于内存对齐,其他的也就不多说了,还是转回结构体吧

   结构体作为一个特殊的类型,也可以像函数一样进行嵌套,比如下面的这个例子

struct A     //定义了一个结构体A
{
   int i;     
   char j;
   struct B;    //内部嵌套了一个结构体B
}
struct B     //定义了一个结构体B
{
   int p;
   float s;
   struct A;    //内部嵌套了一个结构体A
}

     这就是典型的结构体嵌套,但是,有一点问题需要你们注意,在嵌套的时候,因为编译器并不知道你在后面才定义了一个结构体B,它会默认不存在结构体B,所以你必须在A之前就定义B,这样程序才不会报错,虽然是嵌套,但是A,B里面的数据还是会原封不动的输出,不会产生多大影响,除非它内部的数据进行了一些运算。

      结构体指针

  定义一个指针指向这个结构体,那么这个指针就可以通过结构体的地址访问里面的元素,这个用法和函数指针的用法类似。因为指针作为一种数据类型,它也有自己的地址,而只要有地址,就可以用一个指针来访问其内部元素,当然,这样也确实比再写下结构体的一大串代码方便多了,我在下面就定义一个* P指向结构体A

struct A
{
  int i;
  char b;
  float c;
}*P   //指向结构体A的指针

这样做,我想访问哪个元素,就可以直接访问到了,十分方便,当然,你也得清楚一点,结构体的地址和第一个元素的地址一致,要想验证,只需要%p,就可以取出来地址验证了。

结构体的自引用

 在结构体中还可以包含一个类型为该结构体本身的成员,这就叫做结构体的自引用,下面,我就举一个简单的例子

struct B
{
   int data;
   struct B*next;
}
值得注意的是,在进行自引用的时候,必须写出结构体的名字,然后再用解引用符号*,这样才可以正确的进行自引用的操作
关于结构体,我就说这么多啦,前面说的有些赘述,后面就精简一些了,大佬们,欢迎多交流啊。





    

   
     

                   

猜你喜欢

转载自blog.csdn.net/zb1593496558/article/details/78619716
今日推荐