3.
&
数组名
对于 int arr[10];
如果对其分别打印&arr和arr的地址,可以得到
得到两个地址是相同的,但两者的意义是完全不同的,在对其进行&arr+1和arr+1取地址,得到如果如下
两个地址相差36,为16*2+4;其原因是因为&符号是将整个数组当做一个整体,再取其地址,也就是整个数组的首地址,而直接arr取得的地址是这个数组的首元素的首地址.倘若进行&arr+1操作,则是跳过整个数组,取得的地址就要在原有的地址上加上整个数组所占的字节数,而进行arr+1操作,只要在原基础上加上一个 int所占的字符数就可以.
4.函数指针
函数指针是一个指向函数的指针
形如void
(
*
pfun1
)() 是一个函数指针,其原因是
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。
5.函数指针数组
形如 int
(
*
parr
[
10
])(); 则是一个函数指针数组
parr
先和
[]
结合,说明
parr
是数组,数组的内容是 int (*)()
类型的函数指针。
接下来 进行一组练习题
1.int main()
{
int
a
[
5
]
=
{
1
,
2
,
3
,
4
,
5
};
int *
ptr
=
(
int *
)(
&
a
+
1
);
printf
(
"%d,%d"
,
*
(
a
+
1
),
*
(
ptr
-
1
));
return
0
;
}
此代码的输出结果是2,5
其原因是a是元素的首元素地址,所以a+1是先将a进行隐式转换成指针a,在进行加一操作,得到此数组里第二个元素的地址,在进行*解引用操作,得到值为2
而&a是将数组a当做一个整体,取整个数组的地址,在进行加一操作,就是跳过整个数组,指针直接指向这个数组之后的第一个地址,在进行强制类型转换为int*类型,当ptr-1时,就是指这个指针向后偏移一个int ,指向了数组的最后一个元素5,在进行*操作,得到了结果为5.
2.
struct
Test
{
int
Num
;
char *
pcName
;
short
sDate
;
char
cha
[
2
];
short
sBa
[
4
];
}
*
p = (struct test*)0x100000
;
int
main
()
{
printf
(
"%p\n"
,
p
+
0x1
);
printf
(
"%p\n"
, (
unsigned long
)
p
+
0x1
);
printf
(
"%p\n"
, (
unsigned int*
)
p
+
0x1
);
return
0
;
}
![](https://img-blog.csdnimg.cn/6b813ce6632c4fe7abdc68a623c336ef.png)
第一个结果为0x100014,其原因是因为p+0x1 就是将结构体指针p当做一个整体,并且跳过整个结构体,结构体的大小事20个字节,所以为0x100014;特别注意的是20个字节要转成16进制的数字,所以为14
第二个结果为00100001,其原因是(unsigned long)p结构体指针强制转换为一个long类型的整数,整数进行+1操作,得到00100001
第三个结果是因为(unsigned int*)p将将这个结构体指针强制转换为一个无符号的int* 类型,占四个字节,所以为0010004
3.
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
;
}
第一个结果的原因是&arr+1是指向这个数组向后的一个地址,在强制转换为一个int*类型,在打印的时候ptr[-1]相当于指针向前移动一个元素,指向了4