目录
一.
int
main
()
{
int
a
[
5
]
=
{
1
,
2
,
3
,
4
,
5
};
int *
ptr
=
(
int *
)(
&
a
+
1
);
printf
(
"%d,%d"
,
*
(
a
+
1
),
*
(
ptr
-
1
));
return
0
;
}
程序运行的结果是什么?
1.1分析
&a在这里取得的是整个数组的地址,&a+1后跳到数组的最后;
ptr所存放的地址就是数组结束的后面(元素”5“的后面的地址),类型为int (*)[5];
再强制类型转化为int (*);
*(a+1)这里的a代表数组首元素的地址,加一后解引用表示第二个元素,结果为2;
*(ptr-1)表示原来在“5”的后面,减1后,指向5的地址,解引用为5.
结果展示
1.2代码
#include<stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
//程序的结果是什么?
二.
struct
Test
{
int
Num
;
char *
pcName
;
short
sDate
;
char
cha
[
2
];
short
sBa
[
4
];
}
*
p
;
//
假设
p
的值为
0x100000
。 如下表表达式的值分别为多少?
//
已知,结构体
Test
类型的变量大小是
20
个字节
int
main
()
{
printf
(
"%p\n"
,
p
+
0x1
);
printf
(
"%p\n"
, (
unsigned long
)
p
+
0x1
);
printf
(
"%p\n"
, (
unsigned int*
)
p
+
0x1
);
return
0
;
}
/*注:这里是在x86的环境下运行。
2.1解析
首先我们要知道*p为结构体指针;
p+ox1表示的是地址加1,p为结构体指针,加一跳过20个字节,结果为0x100014;
(unsigned long)p是将指针转化为无符号长整形的数,数字加一,再以地址的形式输出,结果为0x100001;
(unsigned int*)p是先将p转化为无符号整形指针类型,加一,跳过4个字节,结果为0x100004;
结果展示
/*注:这里我们的地址只是假设的。
2.2代码
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0; }
三.
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
;
}
3.1解析
&a+1指向的是数组结尾的后面,类型为int (*)[]4;在强制类型转化为int(*);
ptr1[-1]等价于*(ptr1-1),类型为int *, 这里输出结果为4;
(int)a+1是想将a类型转化为int ,再加上1,a原先是地址,转化成int ,是将地址转化成int 型,如图(这里为小端存储)
*ptr2为2 00 00 00
结果展示
3.2代码
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;
}