struct结构体占内存大小计算

以下为在32位编译环境下的信息
1字节:char
2字节:short(不管是不是signed或unsigned)
4字节:int、long、float(不管是不是signed或unsigned)
8字节:double
如果等号是'='这种字符常量的话当然是1字节,如果是“=”这种字符串常量当然是2字节 

struct结构体占用的大小是和编译器有关的,在VC和GCC中可能同一个结构体会有不同的大小。

以一个例子引入:

注意:struct 的{}后面要加上 ”;“

例子1

#include<stdio.h>
struct A
{
           int a;
          double b;
           char c;
};
struct B
{
           double b;
            char c;
            int a;
};
struct C
{
            int a;
            char c;
            double b;
};
int main(void)
{
          A aa;
          B bb;
          C cc;
          printf("A = %d\n", sizeof(aa));//结果:A = 24
          printf("B = %d\n", sizeof(bb));//结果:B = 16
          printf("C = %d\n", sizeof(cc));//结果:C = 16
          return 0;
}
int类型一般是占用四个字节,char类型一般占用一个字节,double类型一般占用8个字节。
1、结构体A首先给int a 分配四个字节,并且以4个字节对齐;然后给double b分配8个字节,发现以4个字节对齐不行,就以8个字节对齐,前面只有int a ,所以int a将占用8个字节;最后为了对齐,将给char c 也分配8给字节,所以结构体A占用了24个字节。
2、结构体B首先给double 分配8个字节,并且以8给字节对齐;然后给char c分配8给字节;最后给int a分配空间的时候发现,前面空有7个字节空间可以放下int a,int a 就和char c一起占用8个字节,所以结构体B占用了16个字节

而在GNU GCC编译器中,遵循的准则有些区别,对齐模数不是像上面所述的那样,根据最宽的基本数据类型来定。在GCC中,对齐模数的准则是:对齐模数最大只能是4,也就是说,即使结构体中有double类型,对齐模数还是4,所以对齐模数只能是1,2,4。而且在上述的三条中,第2条里,offset必须是成员大小的整数倍,如果这个成员大小小于等于4则按照上述准则进行,但是如果大于4了,则结构体每个成员相对于结构体首地址的偏移量(offset)只能按照是4的整数倍来进行判断是否添加填充。
看如下例子:

struct T
{
  char ch;
  double     ;
};
那么在GCC下,sizeof(T)应该等于12个字节。


例子2

struct 大小,与pack的大小(在程序中显示设置#pragma pack(),vc6.0默认大小为8)、结构中最大占用有关

struct A
{

 int a;     0-3

               4-7     要填充(padding)以保证内存对齐的原则
 double b; 8-15
 char c[9]; 16-24
};

首先给a分配内存,因为int占四个字节<pack大小(8个字节),所以按照4个字节对齐,起始位值为0,0%4=0,a最后占的内存为0-3;

接着给b分配内存,double占8个字节,所以按照8个字节对齐,起始位为8(8%8=0),b为8-15;

最后char占一个字节,所以c为16-24;

因此结构体A的大小为8+8+9 = 25;有因为25不是结构体中最大占用内存类型double类型大小(8)的整数倍,所以A最后的大小是32;

例子3

struct B

{
int a;   

double b;     
double c;    
char d;   

};

同理,按上面的分析方法确定各个变量在内存中的位置:
a,0-3;

  ,4-7;
b,8-15;
c,16-23;
d,24;

TOTAL = 25

25 不是8的倍数,所以最后B大小是32;

参考出处: http://blog.163.com/l_c_2005/blog/static/73746124201122333833/


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用共享内存,应该有如下步骤: 1.开辟一块共享内存 shmget() 2.允许本进程使用共某块共享内存 shmat() 3.写入/读出 4.禁止本进程使用这块共享内存 shmdt() 5.删除这块共享内存 shmctl()或者命令行下ipcrm ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。 shmkey = ftok( "mcut" , 'a' ); // 计算标识符 操作共享内存,我们用到了下面的函数 #include #include #include int shmget( key_t shmkey , int shmsiz , int flag ); void *shmat( int shmid , char *shmaddr , int shmflag ); int shmdt( char *shmaddr ); shmget()是用来开辟/指向一块共享内存的函数。参数定义如下: key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。但是刚才我们的两个进程没有任何关系,所以就用ftok()算出来一个标识符使用了。 int shmsiz 是这块内存的大小. int flag 是这块内存的模式(mode)以及权限标识。 模式可取如下值: 新建:IPC_CREAT 使用已开辟的内存:IPC_ALLOC 如果标识符以存在,则返回错误值:IPC_EXCL 然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。 如: IPC_CREAT | IPC_EXCL | 0666 这个函数成功时返回共享内存的ID,失败时返回-1。 // shmid开辟共享内存 shmid = shmget( shmkey , sizeof(in_data) , IPC_CREAT | 0666 ) ; shmat()是用来允许本进程访问一块共享内存的函数。 int shmid是那块共享内存的ID。 char *shmaddr是共享内存的起始地址 int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式 成功时,这个函数返回共享内存的起始地址。失败时返回-1。 char *head , *pos , head = pos = shmat( shmid , 0 , 0 ); // 允许本进程使用这块共享内存 shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。 参数char *shmaddr是那块共享内存的起始地址。 成功时返回0。失败时返回-1。 shmdt( head ); // 禁止本进程使用这块内存 此外,还有一个用来控制共享内存的shmctl()函数如下: #include #include #include int shmctl( int shmid , int cmd , struct shmid_ds *buf ); int shmid是共享内存的ID。 int cmd是控制命令,可取值如下: IPC_STAT 得到共享内存的状态 IPC_SET 改变共享内存的状态 IPC_RMID 删除共享内存 struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。 返回值: 成功:0 失败:-1 shmctl(shmid,IPC_RMID,NULL); 刚才我们的mpaste.c程序中还可以加入这样几句。 struct shmid_ds buf; ... ... shmctl( shmid , IPC_STAT , &buf ); // 取得共享内存的状态 ... ... shmctl( shmid , IPC_RMID , &buf ); // 删除共享内存 注意:在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。 简单解释一下ipcs命令和ipcrm命令。 取得ipc信息: ipcs [-m|-q|-s] -m 输出有关共享内存(shared memory)的信息 -q 输出有关信息队列(me

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值