C语言,内存对齐,内存分配,地址操作,结构体(二)

上次在操作结构体地址的时候,本来想取结构体第二个成员变量的地址,就在第一个成员变量基址上增加了第一个成员变量的大小,但是发现结果不对

struct student
{
	int a;
	int b;
	double c;
};
查看一下结构体的地址

        printf("stu size %d\n",sizeof(stu));
	printf("stu.a address %x\n",&stu.a);
	printf("stu.b address %x\n",&stu.b);
	printf("stu.c address %x\n",&stu.c);
	printf("stu+1 address %x\n",&stu+1);
结果如下:

stu size 16
stu.a address 28fed0
stu.b address 28fed4
stu.c address 28fed8
stu+1 address 28fee0
stu+1的地址正好比stu增加了sizefo(stu)。也就是说在结构体起始地址增加加1,不是简单增加一个字节,或者说向后顺推一个字节,而是增加了整个结构体的大小,移动sizeof(stu)大小,(寻找下一个结构体)。

c语言中,对指针加1,是将该指针向后移动 该指针存储数据类型的大小,也就是说指针增加一个的本意是寻找下一个存储相同数据类型的存储单元。

下面用几个数据类型验证一下:

	int temp1;
	int temp2;
	printf("temp1 address %x\n",&temp1);
	printf("temp2 address %x\n",&temp2);
地址如下:

temp1 address 28fecc
temp2 address 28fec8
temp1的地址高,现在我们队temp2的地址加1

	printf("temp1 address %x\n",&temp1);
	printf("temp2 address %x\n",&temp2);
	printf("temp2+1 address %x\n",&temp2+1);
结果如下:

temp1 address 28fecc
temp2 address 28fec8
temp2+1 address 28fecc
temp2地址加1操作增加了4个字节,也就是int的大小

再看一下其他数据类型,还有数组

	double temp4;
	char temp5[5];
	int temp6[5];
		
	printf("temp3   address %x\n",&temp3);
	printf("temp3+1 address %x\n",&temp3+1);
	printf("temp4   address %x\n",&temp4);
	printf("temp4+1 address %x\n",&temp4+1);
	printf("temp5   address %x\n",&temp5);
	printf("temp5+1 address %x\n",&temp5+1);
	printf("temp6   address %x\n",&temp6);
	printf("temp6+1 address %x\n",&temp6+1);
结果如下

temp3     address   28fedf
temp3+1 address   28fee0
temp4     address   28fed0
temp4+1 address   28fed8
temp5     address   28fecb
temp5+1 address   28fed0
temp6     address   28feb4
temp6+1 address   28fec8
temp3+1增加了1个字节,char类型

temp4+1增加了8个字节,double字节

temp5+1增加了5*1个字节,长度为5的char数组

temp6+1增加了5*4个字节,长度为5的int数组

话说回来,(&temp6+1)-(&temp)=?多少呢?,肯定是1了

如果用printf("stu.c-stu.b  address   %d\n",&stu.c-&stu.b)进行操作,编译器很直接

假如我们想要通过结构体的首地址得到成员变量的地址,那就强制让编译器增加数据类型的长度

	printf("stu.b  address   %x\n",(char *)&stu.a+sizeof(stu.a));
	printf("stu.c  address   %x\n",(char *)&stu.a+sizeof(stu.a)+sizeof(stu.b));
结果如下:

stu.a  address   28fed0
stu.b  address   28fed4
stu.c  address   28fed8
stu.b  address   28fed4
stu.c  address   28fed8
最后再回到结构体上,本来还想再试试如何通过结构体首地址访问结构体变量或者通过结构体成员变量获得结构体首地址,结果发现linux内核中有两个宏offsetof和container_of。

offsetof宏:获得一个结构体变量成员在此结构体中的偏移量。

container_of宏:从结构体(type)某成员变量(member)指针(ptr)来求出该结构体(type)的首指针。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值