好吧,我承认这个日志很无聊,只是来讨论一下1+1的问题,随便引申一下步长和地址强制转换的问题,要不是jordanli22(也就是本人我)无聊得发慌,他也不会写这日志,哈哈,废话少说,直奔主题。
1.数学运算的1+1
int i = 1;
float f = 1;
double d = 1;
printf("%d\n%f\n%lf\n",i+1,f+1,d+1);
这个就不解释了,都是我们平常理解的1+1=2。只是精度不同而已。这里并不涉及到步长的问题。
2.地址运算
int i = 1;
int *pi =&i;
double *pl = (double *)pi;//强制转换
printf("%X\n%X\n",pi,pi+1);
printf("%X\n%X\n",pi,((unsigned long int)pi+1));//强制转化后变成了普通的数学运算
printf("%X\n%X\n",pl,pl+1);
假设&i = 0x12FF7C 即pi = 0x12FF7C;那么
pi+1=?
(unsigned long int)pi+1 =?
pl+1 =?
这时候还是不是简单的+1呢?通常这样问,结果都是否定的,我好像有自己打自己嘴巴的感觉。
解题分析:
地址相加在上面的日志有介绍过,地址在参与运算时最小单位的字节,而且编译器自动识别此指针的步长,所谓的步长,就是一步跨越的距离,这里表示一次读取多少个字节。
pi是指向整形的指针,sizeof(int) = 4;所以每次跳动4个字节。于是 pi+1= 0x12FF7C + 4 = 0x12FF80;
(unsigned long int)pi+1 = ? ,由于pi已经被强制转换成int,一个int+1只是一个数学运算,不涉及到步长问题,所以(unsigned long int)pi+1 = 0x12FF7C +1 =0x12FF7D;
double *pl = (double *)pi; 从此句可以看到pl虽然和pi一样都是指向i变量的,但是步长不同了,pl每次会取sizeof(double) = 8个字节。所以pl+1 = 0x12FF7C +8 =0x12FF84;
你理解了吗?好,出条题给你测试一下吧:(相信你自己)
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
假设p的值为0x100000.如下表达式的值为多少:
p+0x1=0x_?
(unsigned long)p+0x1=0x_?
(unsigned int*)p+0x1=0x_?