指针笔试题
例1:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
//&a + 1跳过一整个数组,然后强制类型转换成(int*)
//所以指针变量ptr存放的是数组往后一个元素
printf( "%d,%d", *(a + 1), *(ptr - 1));
//a是首元素地址,+1得到第二个元素的地址,*解引用得到2,打印2
return 0;
}
输出:
2 5
例2:
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节,内容对齐
int main()
{
//结构体Test的指针+1,跳过20个字节,转换成十六进制是0x00100014
printf("%p\n", p + 0x1);
//p被强制类型转换成(unsigned long),整形+1,结果是0x00100001
printf("%p\n", (unsigned long)p + 0x1);
//p被强制类型转换成(unsigned int*),无符号整形指针+1,跳过4个字节,结果是0x00100004
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
输出:
00100014
00100001
00100004
注:
指针+1才是跳过该指针类型所占的字节大小,
例3:
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
//(&a + 1)跳过整个数组,ptr1指向的是数组后一个元素
int *ptr2 = (int *)((int)a + 1);
//a是首元素地址,强制类型转换成整形后+1,代表整形1的地址从起始位置往后跳了一个字节
//所以ptr2指针指向的是整形1的地址从起始位置往后跳了一个字节的位置
printf( "%x,%x", ptr1[-1], *ptr2);
//prt1[-1]就是*(ptr1-1),向前跳一个整形,指向数组最后一个元素,*解引用后,打印4
//我用的是小端环境,数据在内存中是倒着放的,指针指向整形1往后一个字节,访问的时候
//指针访问四个字节,就将数组下一个元素整形2的第一个字节也包含了,所以打印20000000
return 0;
}
输出:
4,2000000
例4:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//(0,1),看清楚,这是个逗号表达式,所以
//数组a其实存放的是{ 1, 3, 5 }
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}
输出:
1
例5:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
//a的类型是int(*)[5]
//p的类型是int(*)[4]
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//p[4][2]==*(*(p+4)+2)
//&p[4][2] - &a[4][2]==-4
//地址不存在负数
//-4的源码:1000 0000 0000 0000 0000 0000 0000 0100
// 反码:1111 1111 1111 1111 1111 1111 1111 1011
// 补码:1111 1111 1111 1111 1111 1111 1111 1100
// f f f f f f f c
return 0;
}
输出:
fffffffc,-4
例6:
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);//&aa是一个数组指针类型int(*p)[5]
//&aa+1跳过整个数组
int *ptr2 = (int *)(*(aa + 1));
//aa是数组首行地址,+1得到第二行地址
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//ptr-1向前跳一个整形,得到数组最后一个元素地址,*解引用得到10
//ptr2-1向前跳一个整形,得到数组第一行最后一个元素地址,*解引用得到5
return 0;
}
输出:
10,5
例7:
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
//这个指针数组里存放的是三个字符串的首元素地址
char**pa = a;
//二级指针pa接收了数组a首元素地址
pa++;
//指针++,跳过4个字节,
printf("%s\n", *pa);
//*pa指向第二个字符串的首元素地址,打印at
return 0;
}
输出:
at
例8:
#include <stdio.h>
int main()
{
char* c[] = { "ENTER","NEW","POINT","FIRST" };
//数组中存放四个字符串的首元素地址
char** cp[] = { c + 3,c + 2,c + 1,c };
//这个二级指针数组存放的字符串数组分别是:
//{ "FIRST", "POINT", "NEW", "ENTER" }
char*** cpp = cp;
//三级指针cpp指向cp数组的首元素地址
printf("%s\n", **++cpp);
//cpp++,cpp指向cp数组第二个元素地址,*第一次解引用得到cp数组第二个元素(c+2)
//*第二次解引用cp数组第二个元素,得到c数组第三个元素,打印 POINT
printf("%s\n", *-- * ++cpp + 3);
//cpp++,cpp指向cp数组第三个元素地址,*第一次解引用得到cp数组第三个元素(c+1)
//(c+1)--后等于c,再解引用得到c数组第一个元素,然后+3跳过三个字节,打印 ER
printf("%s\n", *cpp[-2] + 3);
//*cpp[-2]就是**(cpp-2),cpp-2得到cp数组首元素地址,*第一次解引用得到cp数组第二个元素(c+3)
//*第二次解引用cp数组第一个元素,得到c数组第四个元素,+3跳过三个字节,打印 ST
printf("%s\n", cpp[-1][-1] + 1);
//cpp[-1][-1]就是*(*(cpp-1)-1),cpp-1指向cp数组第二个元素地址,*得到cp数组第二个元素(c+2)
//然后-1等于(c+1),*得到c数组第二个元素,+1跳过一个字节,打印 EW
return 0;
}