zoukankan      html  css  js  c++  java
  • struct

    本文部分转载自http://www.cnblogs.com/qyaizs/articles/2039101.html,在此感谢作者!

     1 首先://注意在C和C++里不同
        在C中定义一个结构体类型要用typedef:
        typedef struct Student
        {
        int a;
        }Stu;
        于是在声明变量的时候就可:Stu stu1;(如果没有typedef就必须用struct Student stu1;来声明)
        这里的Stu实际上就是struct Student的别名。Stu==struct Student
        另外这里也可以不写Student(于是也不能struct Student stu1;了,必须是Stu stu1;)
        typedef struct
        {
        int a;
        }Stu;
        但在c++里很简单,直接
        struct Student
        {
        int a;
        };    
        于是就定义了结构体类型Student,声明变量时直接Student stu2;
    ======================================================================================

      2.其次:
        在c++中如果用typedef的话,又会造成区别:
        struct   Student   
        {   
        int   a;   
        }stu1;//stu1是一个变量  

     
        typedef   struct   Student2   
        {   
        int   a;   
        }stu2;//stu2是一个结构体类型=struct Student  

     
        使用时可以直接访问stu1.a
        但是stu2则必须先   stu2 s2;
        然后               s2.a=10;

     

     typedef struct和struct的区别:

     

     

        typedef struct tagMyStruct
        {
         int iNum;
         long lLength;
        } MyStruct;

        上面的tagMyStruct是标识符,MyStruct是变量类型(相当于(int,char等))。

     

     

        这语句实际上完成两个操作:

          1) 定义一个新的结构类型

        struct tagMyStruct
        {  
         int iNum;
         long lLength;
        };

      分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,不论是否有typedefstruct 关键字和tagMyStruct一起,构成了这个结构类型,这个结构都存在。

      我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。

      2) typedef为这个新的结构起了一个名字,叫MyStruct。

        typedef struct tagMyStruct MyStruct;

      因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。

      2.

        typedef struct tagMyStruct
        {
         int iNum;
         long lLength;
        } MyStruct;

        在C中,这个申明后申请结构变量的方法有两种:

        (1)struct tagMyStruct 变量名

        (2)MyStruct 变量名

        在c++中可以有

        (1)struct tagMyStruct 变量名

        (2)MyStruct 变量名

        (3)tagMyStruct 变量名

     

    2016-10-23 17:23:16

     

    计算机组成原理教导我们,这样有助于加快计算机的取数速度,否则就得多花指令周期了。

     

    为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上。
    字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
        1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
        2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
        3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。

     

     

    结构体对齐问题,结构体以体内字段的内存占用数最大的字段为基本对齐基础。

    指定对齐方式

    可以使用#pragma pack(N)来指定结构体成员的对齐方式
    对于指定的对齐方式,其成员的地址偏移以及结构的总的大小也有下面三个约束条件

      1. 结构体第一个成员的地址和结构体的首地址相同
      2. 结构体每个成员的地址偏移需要满足:N大于等于该成员的大小,那么该成员的地址偏移需满足默认对齐方式(地址偏移是其成员大小的整数倍);N小于该成员的大小,那么该成员的地址偏移是N的整数倍。(结构体成员对齐的规则如下: 将自己的本身在内存中实际占用的字节和当前由#pragma pack(n)设定的n进行比较,取其中最下的那个作为结构体当前成员的对齐方式,但是不影响其他结构体成员的对齐方式。)
      3. 结构体总的大小需要时N的整数倍,如果不是需要在结构体的末尾进行填充。
      4. 如果N大于结构体成员中最大成员的大小,则N不起作用,仍然按照默认方式对齐。

     

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <errno.h>
     4 #include <stdlib.h>
     5 #include <signal.h>
     6 #include <string.h>
     7 #include <iostream>
     8 #include <sys/wait.h>
     9 #pragma pack(2)//#pragma pack(n)这个预处理,主要的功能是改变内存对齐方式的选项,按照给定的n字节进行内存对齐
    10 using namespace std;
    11 struct test{
    12     char a;
    13     int b;
    14     short c;
    15 }test;
    16 struct test1{
    17     char a;
    18     long b;
    19     short c;
    20     char d;
    21 }test1;
    22 struct test2{
    23    char a;
    24    short b;
    25    char c;
    26    long d;
    27 }test2;
    28 struct buffer
    29 {
    30     long data_len;   //长度
    31     char d;
    32     char data[0];  //起始地址
    33 }buffer;
    34 int main()
    35 {
    36     printf("test$$$$$$$$$$$$$$$:%lu
    ", sizeof(test));//12
    37     printf("%#x %#x %#x
    ", &test.a, &test.b, &test.c);
    38     printf("test1@@@@@@@@@@@@@:%lu
    ", sizeof(test1));//24
    39     printf("%#x %#x %#x %#x
    ", &test1.a, &test1.b, &test1.c, &test1.d);
    40     printf("test2###########:%lu
    ", sizeof(test2));//16
    41     printf("%#x %#x %#x %#x
    ", &test2.a, &test2.b, &test2.c, &test2.d);
    42     printf("buffer############:%lu
    ", sizeof(buffer));//16
    43     printf("%#x %#x %#x
    ", &buffer.data_len, &buffer.d, &buffer.data);
    44 
    45     return 0;
    46 }
     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <iostream>
     6 using namespace std;
     7 typedef struct test0{
     8     char a[3];
     9     int b;
    10     char c;
    11 }sttest0;
    12 typedef struct test1{
    13     char a[4];
    14     int b;
    15     char c;
    16 }sttest1;
    17 typedef struct test2{
    18     char a[7];
    19     int b;
    20     char c;
    21 }sttest2;
    22 typedef struct test3{
    23     char a[8];
    24     int b;
    25     char c;
    26 }sttest3;
    27 typedef struct test4{
    28     char a[9];
    29     int b;
    30     char c;
    31 }sttest4;
    32 int main()
    33 {
    34     printf("%lu %lu %lu %lu %lu
    ", sizeof(sttest0), sizeof(sttest1), sizeof(sttest2), sizeof(sttest3), sizeof(sttest4));
    35 
    36     printf("address$$$$$$$$$$$$$$$$$
    ");
    37     sttest0 t0;
    38     sttest1 t1;
    39     printf("%p %p %p
    ", &t0.a, &t0.b, &t0.c);
    40     printf("%p %p %p
    ", &t1.a, &t1.b, &t1.c);
    41     return 0;
    42 }

  • 相关阅读:
    vuex之store拆分即多模块状态管理
    vue项目中使用vueX
    vue中父子组件的参数传递和应用
    VUE中使用vue-awesome-swiper
    VUE真实项目中常用的生命周期和参数
    VUE生命周期
    vue+mockjs 模拟数据,请求回调的应用
    Vue项目搭建与部署还有调试插件Vue.js devtools
    tableTD中添加对角斜线
    前端面试题及答案,理论知识
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/4788741.html
Copyright © 2011-2022 走看看