[算法题] 计算结构体的大小

来源:互联网 发布:最新新卡购系统源码 编辑:程序博客网 时间:2024/06/08 16:51
计算结构体的大小

     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_Henum 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 0tblNode 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("\nsize = %d \t 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!\r\n");        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!\r\n");}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!\r\n");}int _tmain(int argc, _TCHAR* argv[]){    TestCase01();    TestCase02();    return 0;}
View Code
 
原创粉丝点击