1、打印地址位置
*************************************************/
<span style="font-size:12px;">#include<stdio.h>
#include<stdlib.h>
void main()
{
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
printf("p1+5: %x",p1+5);
printf("p2+5: %x",p2+5);
system("pause");
}</span>
解析:p1指向字符型,一次移动一个字符型,1个字节;p1+5后移5个字节,16进制表示为5;
p2指向长整型,一次移动一个长整型,4个字节,p2+5后移20字节,16进制表示为14。
{ char每次移动1个字节;short移动2个字节;int ,long ,float移动4个字节;double移动8个字节}
/*************************************************
2、判断字节大小
*************************************************/
#include<stdio.h>
#include<stdlib.h>
void main()
{
struct S1
{
int i;//可认为i和name按四字节对齐
char name[20]; //但是占前面占int型的4字节后,按字节对齐,可以自身偏移19字节即可。
double c; //因为前面所占字节是8的整数倍,因此前面部分不需要偏移,c占8字节
char l; //偏移7字节保证8字节对齐
};
struct A
{
char t:4; //位域,意思是指char类型变量t只使用低4位表示
char k:4;
unsigned short i:8; //位域,意思是指变量i只使用低8位表示,到此处共占2字节
unsigned long m;//unsigned long为4字节, 前面偏移2字节保证4字节对齐
};
char name1[17];
printf("S1字节长度为:%d\n",sizeof(S1));//40字节
printf("A字节长度为:%d\n",sizeof(A));//8字节
printf("sizeof(name1):%d\n",sizeof(name1));//17字节
system("pause");
}
对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:
数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
联合 :按其包含的长度最大的数据类型对齐。
结构体: 结构体中每个数据类型都要对齐。
比如有如下一个结构体:
struct stu{
char sex;
int length;
char name[10];
};
struct stu my_stu;
由于在x86下,GCC默认按4字节对齐,它会在sex后面跟name后面分别填充三个和两个字节使length和整个结构体对齐。于是我们sizeof(my_stu)会得到长度为20,而不是15.
其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;例如上面第二个结构体变量的地址空间。
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。例如上面第一个结构体变量。