第四章 指针和数组
一.地址的强制转换
先看下面的例子:
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
假设p的值为0x100000 ,那么下面这些表达式的值分别是多少?
1).p+ 0x1 =0x_____?
2).(unsigned long)p +0x1 =0x____?
3).(unsigned int*)p +0x1 =0x____?
解析:
1).指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数,这个整数的单位不是字节而是元素个数 p+0x1 的值为0x100000 + sizeof(Test)*0x1 至于此结构体的大小为20字节,最后计算出p +0x1 的值为0x100014;
2).(unsigned long ) p+ 0x1 的值呢?这里涉及强制转换,将指针变量p保存的值强制转换成无符号长整型数。任何数值一旦被强制转换,其类型就改变了,所以这个表达式其实就是一个无符号的长整型数加上另一个整数,其值为0x100001 .
3).(unsigned int *)p +0x1 的值呢? 这里的p被强制转换成一个指向无符号整型的指针,所以其值为:0x100000 +sizeof (unsigned int) *0x1 =0x100004
上面似乎没有什么技术含量,下面来个有技术含量的:在x86系统下,其值为多少?
int main()
{
int a[4] ={1,2,3,4};
int *ptr1=(int * )(&a +1);
int *ptr2 =(int*)((int)a+1);
printf("%x ,%x",ptr1[-1],*ptr2);
return 0;
}
这个据说在网上难道了n多人,但据说懂汇编的人就会解....
在懂&a+1 和a+1区别的基础上
ptr1 :将&a+1的值强制转换为int *类型,赋值给int * 类型的变量ptr1,ptr1 指向数组a的下一个int类型的数据了。ptr1[-1]被解析为*(ptr1-1),即ptr1往后退4字节,所以其值为0x4.
prt2 :(int)a+1 的值为元素a[0]的第2个字节的地址,然后把这个地址强制转换为int *类型的值赋值给ptr2,也就是说 *ptr2的值应该为元素a[0]的第2个字节开始的连续4字节的内容----看图:
这连续4字节到底是什么东西呢?也就是说a[0]、a[1]里到底存怎么存储?这就涉及系统的大小端模式了。