zoukankan      html  css  js  c++  java
  • [算法题] 计算结构体的大小

    计算结构体的大小

         C代码中定义的结构体是一块连续内存,各成员按照定义的顺序依次在其中存放。编译器在完成语法分析后,需要计算它的大小,然后才能正确地为结构体分配空间。为了让结构体的所有成员都能正确、快速地访问,需要字节对齐。

         字节对齐体现为:在成员之间可能增加补齐字节,以调整每个成员的偏移;结构体末尾,也可能增加补充字节。所有补齐字节计入结构体的大小。

         请写一个程序来计算结构体的大小,要考虑字节对齐,同时要支持结构体多层嵌套的情况。

    结构体大小的计算

    成员在结构体内的偏移必须是它的字节对齐值的倍数。

     
    l 字节对齐值: 
       1)基本类型char、short、int、double的字节对齐值依次为1、2、4、8。
       2)数组的字节对齐值等于它的一个元素的字节对齐值。
       3)结构体的字节对齐值等于它的所有成员的字节对齐值的最大值。
     
    2 大小的计算: 
      1)基本类型char、short、int、double的大小依次为1、2、4、8字节。
      2)数组的大小等于它的一个元素的大小乘以元素个数。
      3)结构体的大小要补齐到它自己的字节对齐值的倍数,补齐字节在末尾。

    要求

    实现以下接口:

    1.开始结构体定义 
    2.添加基本类型成员
    3.添加数组成员 
    4.添加嵌套结构体成员
    5.结束嵌套结构体成员
    6.完成结构体定义,输出它的大小 

    调用者会保证: 

    1.结构体的开始和结束是匹配的。 
    2.不需要考虑空的结构体。
    3.数组只限于一维的基本类型的数组。 
    4.最多20层嵌套(嵌套的情况参考示例)
     
    StructSize.h
    #ifndef _STRUCT_SIZE_H
    #define _STRUCT_SIZE_H
    
    enum Type { CHAR_TYPE, SHORT_TYPE, INT_TYPE, DOUBLE_TYPE };
    
    /*********************** 自定义数据结构 **************************/
    typedef struct _tblNode
    {
        enum Type type;
        int  size;
    }tblNode;
    
    typedef struct _structType
    {
        int size;
        int align;
    }StructType;
    /******************************************************************/
    
    
    /* 功能:开始定义结构体
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int start_struct(void);
    
    /* 功能:添加基本类型成员
     * 输入:类型
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int add_basic_type(enum Type type);
    
    /* 功能:添加数组类型成员
     * 输入:type:数组元素类型
     *    number:数组元素数
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int add_array(enum Type type, unsigned int number);
    
    /* 功能:添加嵌套结构体成员
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int begin_nested_struct(void);
    
    /* 功能:结束嵌套结构体成员
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int end_nested_struct(void);
    
    /* 功能:完成结构体定义,计算它的大小
     * 输入:无
     * 输出:size:结构体大小
     * 返回:正常返回0,失败返回-1
     */
    int finish_struct(unsigned int *size);
    
    #endif
    View Code
    StructSize.cpp
    // StructSize.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "StructSize.h"
    #include <stdio.h>
    
    #define PRINT_ON 0
    
    tblNode g_tbl[] =
    {
        {CHAR_TYPE,   1},
        {SHORT_TYPE,  2},
        {INT_TYPE,    4},
        {DOUBLE_TYPE, 8},
    };
    
    StructType g_astResult[20] = {0};
    int g_iIndex = 0;
    
    void Print(void)
    {
    #if PRINT_ON   
        printf("
    size = %d 	 align = %d", g_astResult[g_iIndex].size, g_astResult[g_iIndex].align);
    #endif
    }
    
    /* 功能:开始定义结构体
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int start_struct(void)
    {
        g_iIndex = 0;
           g_astResult[g_iIndex].size  = 0;
        g_astResult[g_iIndex].align = 1;
        return 0;
    }
    
    /* 功能:添加基本类型成员
     * 输入:类型
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int add_basic_type(enum Type type)
    {
        int iSize = 0;
        
        if (type > DOUBLE_TYPE)
        {
            return -1;
        }
    
        iSize = g_tbl[type].size;
        while (0 != g_astResult[g_iIndex].size % iSize)
        {
            g_astResult[g_iIndex].size++;
        }
    
        g_astResult[g_iIndex].size += iSize;
        g_astResult[g_iIndex].align = (g_astResult[g_iIndex].align > iSize) ? g_astResult[g_iIndex].align : iSize;
    
        Print();
        return 0;
    }
    
    /* 功能:添加数组类型成员
     * 输入:type:数组元素类型
     *    number:数组元素数
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int add_array(enum Type type, unsigned int number)
    {
           int iSize = 0;
        
        if (type > DOUBLE_TYPE)
        {
            return -1;
        }
    
        iSize = g_tbl[type].size;
        while (0 != g_astResult[g_iIndex].size % iSize)
        {
            g_astResult[g_iIndex].size++;
        }
    
        g_astResult[g_iIndex].size += iSize * number;
        g_astResult[g_iIndex].align = (g_astResult[g_iIndex].align > iSize) ? g_astResult[g_iIndex].align : iSize;
    
        Print();
        return 0;
    }
    
    /* 功能:添加嵌套结构体成员
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int begin_nested_struct(void)
    {
        g_iIndex++;
        g_astResult[g_iIndex].size  = 0;
        g_astResult[g_iIndex].align = 1;
    
        Print();
        return 0;
    }
    
    /* 功能:结束嵌套结构体成员
     * 输入:无
     * 输出:无
     * 返回:正常返回0,失败返回-1
     */
    int end_nested_struct(void)
    {
        int iFatherStructSize = 0;
        int iSonStructSize = 0;
        
           while (g_astResult[g_iIndex].size % g_astResult[g_iIndex].align != 0)
        {
            g_astResult[g_iIndex].size++;
        }
        g_iIndex--;
    
        if (g_iIndex >= 0)
        {
            iFatherStructSize = g_astResult[g_iIndex].align;
            iSonStructSize    = g_astResult[g_iIndex + 1].align;
            g_astResult[g_iIndex].align = (iFatherStructSize > iSonStructSize) ? iFatherStructSize : iSonStructSize;
            while(g_astResult[g_iIndex].size% g_astResult[g_iIndex].align != 0)
            {
                g_astResult[g_iIndex].size++;
            }
            g_astResult[g_iIndex].size += g_astResult[g_iIndex + 1].size;
        }
    
        Print();
        return 0;
    }
    
    /* 功能:完成结构体定义,计算它的大小
     * 输入:无
     * 输出:size:结构体大小
     * 返回:正常返回0,失败返回-1
     */
    int finish_struct(unsigned int *size)
    {
        if (0 != g_iIndex)
        {
            return -1;
        }
    
        while (0 != g_astResult[g_iIndex].size % g_astResult[g_iIndex].align)
        {
            g_astResult[g_iIndex].size++;
        }
        *size = g_astResult[g_iIndex].size;
        
        Print();
        return 0;
    }
    View Code

    main.cpp

    // StructSize.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "StructSize.h"
    #include <iostream>
    
    void CPPUNIT_ASSERT(int iRet)
    {
        if (0 == iRet)
        {
            printf("ERROR!
    ");
            system("pause");
        }
    }
    
    void TestCase01()
    {
        unsigned int size;
        CPPUNIT_ASSERT(0 == start_struct());
        CPPUNIT_ASSERT(0 == add_basic_type(INT_TYPE));
        CPPUNIT_ASSERT(0 == begin_nested_struct());
        CPPUNIT_ASSERT(0 == add_basic_type(SHORT_TYPE));
        CPPUNIT_ASSERT(0 == begin_nested_struct());
        CPPUNIT_ASSERT(0 == add_basic_type(DOUBLE_TYPE));
        CPPUNIT_ASSERT(0 == end_nested_struct());
        CPPUNIT_ASSERT(0 == end_nested_struct());
        CPPUNIT_ASSERT(0 == add_array(CHAR_TYPE, 2));
        CPPUNIT_ASSERT(0 == finish_struct(&size));
        CPPUNIT_ASSERT(size == 32);
        printf("TestCase01 Ok!
    ");
    }
    
    void TestCase02()
    {
        unsigned int size = 0;
        CPPUNIT_ASSERT(0 == start_struct());
        CPPUNIT_ASSERT(0 == add_basic_type(INT_TYPE));
        CPPUNIT_ASSERT(0 == add_basic_type(DOUBLE_TYPE));
        CPPUNIT_ASSERT(0 == add_basic_type(SHORT_TYPE));
        CPPUNIT_ASSERT(0 == add_array(CHAR_TYPE, 3));
        CPPUNIT_ASSERT(0 == finish_struct(&size));
        CPPUNIT_ASSERT(size == 24);
        printf("TestCase02 Ok!
    ");
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        TestCase01();
        TestCase02();
        return 0;
    }
    View Code
     
  • 相关阅读:
    JDK下载 安装 配置
    C#中的委托与事件 笔记
    转载 -- C# 中的委托和事件
    Laravel5 路由问题 /home页面无法访问
    eclipse的android智能提示设置
    svn在linux下的使用(ubuntu命令行模式操作svn)
    gdb结合coredump定位崩溃进程
    Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
    struct的初始化,拷贝及指针成员的使用技巧
    C++ 资源大全
  • 原文地址:https://www.cnblogs.com/jingmoxukong/p/3393834.html
Copyright © 2011-2022 走看看