指针笔试题
笔试题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; } //程序的结果是什么?
解析
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)); // 2,5 //a+1 a首元素地址,加一后得到第二个元素地址 // *(a + 1)解引用后得到 2 //ptr指针类型为int* ptr指向数组末尾 //ptr-1得到数组最后一个元素地址 // *(ptr - 1) 解引用得到最后一个元素5 return 0; }
笔试题2
//这里已知结构体的大小是20个字节 struct Test { int Num; char *pcName; short sDate; char cha[2]; short sBa[4]; }*p; //假设p 的值为0x100000。 如下表表达式的值分别为多少? int main() { printf("%p\n", p + 0x1); printf("%p\n", (unsigned long)p + 0x1); printf("%p\n", (unsigned int*)p + 0x1); return 0; }
解析
//这里已知结构体的大小是20个字节 struct Test { int Num; char* pcName; short sDate; char cha[2]; short sBa[4]; }*p; //假设p 的值为0x100000。 如下表表达式的值分别为多少? int main() { p = (struct Test*)0x100000; printf("%#08x\n", p + 0x1); //0x00100020 //p是结构体指针类型,p+1跳过一个结构体大小 //结构体大小为20字节,所以跳过20 // 0x100000+20 = 0x00100020 printf("%#08x\n", (unsigned long)p + 0x1);//0x100001 //(unsigned long)p 将0x100000强制类型转换 //转换成unsigned long 后 + 0x1就是直接加 //0x100000 + 0x1 = 0x100001 printf("%#08x\n", (unsigned int*)p + 0x1);//0x100004 //(unsigned int*)p 转换成 (unsigned int*)p // 加 1跳过一个unsigned int类型大小 4 //0x100000 + 4 =0x100004 return 0; }
笔试题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; }
解析
int main() { int a[4] = { 1, 2, 3, 4 }; int* ptr1 = (int*)(&a + 1); //&a得到数组地址,&a+1跳过一个数组 //(int*)(&a+1)将数组指针强制转换 int* ptr2 = (int*)((int)a + 1); //(int)a 将a数组首元素地址强制转换int //(int)a+1后,a的地址码 + 1 //(int*)(int)a+1 转换成int*指针 printf("%x,%x", ptr1[-1], *ptr2);//4 , 2000000 //ptr1-1减去int类型大小,向前移动一个int型 //ptr2 指向了整个数组的第二个字节,访问一个int型 return 0; }
笔试题4
#include <stdio.h> int main() { int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int *p; p = a[0]; printf( "%d", p[0]); return 0; }
解析
int main() { int a[3][2] = { (0, 1), (2, 3), (4, 5) }; //逗号表达式,初始化为{1,3,5} int* p; p = a[0]; //将a[0]第一行地址存入int*类型的p中 //即类型进行了转换成了int* printf("%d", p[0]);// 1 //此时的 p 是第一行第一个元素的地址 //p[0]就是 1 return 0; }
笔试题5
int main() { int a[5][5]; int(*p)[4]; p = a; printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); return 0; }X
解析
int main() { int a[5][5]; int(*p)[4]; //p为int [4] 类型的数组指针 p = a; //a为首元素地址,第一行的地址 //a为 int [5]数组指针 //将 a 赋值给 p printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); // fffffffc -4 // &p[4][2] - &a[4][2] = -4 return 0; }
笔试题6
int main() { int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int *ptr1 = (int *)(&aa + 1); int *ptr2 = (int *)(*(aa + 1)); printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1)); return 0; }
解析
int main() { int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int* ptr1 = (int*)(&aa + 1); //&aa+1 跳过一个数组大小,数组指针 // aa+1指向数组的末尾 //(int*)(&aa + 1)转换成int*指针 int* ptr2 = (int*)(*(aa + 1)); //aa+1首元素地址 + 1 指向第二个元素地址 // 而这里的首元素地址就是第一行地址 // 加一后指向第二行地址 //(int*)(*(aa + 1))转换成 int*指针 printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5 //ptr1-1数组末尾指针-1 ptr1是int*指针 // 所以减一得到 最后一个元素地址 // 解引用后得到元素 10 //ptr2-1第二行数组地址-1 // 因为prt2是int*指针类型-1 跳过一个int类型 //*(ptr2-1)得到第一行最后一个元素 5 return 0; }
笔试题7
#include <stdio.h> int main() { char *a[] = {"work","at","alibaba"}; char**pa = a; pa++; printf("%s\n", *pa); return 0; }
解析
int main() { char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; //pa++ 后指向char* "at" printf("%s\n", *pa); // at return 0; }
笔试题8
int main() { char *c[] = {"ENTER","NEW","POINT","FIRST"}; char**cp[] = {c+3,c+2,c+1,c}; char***cpp = cp; printf("%s\n", **++cpp); printf("%s\n", *--*++cpp+3); printf("%s\n", *cpp[-2]+3); printf("%s\n", cpp[-1][-1]+1); return 0; }
解析
int main() { char* c[] = { "ENTER","NEW","POINT","FIRST" }; char** cp[] = { c + 3,c + 2,c + 1,c }; char*** cpp = cp; printf("%s\n", **++cpp); //POINT printf("%s\n", *-- * ++cpp + 3);//ER printf("%s\n", *cpp[-2] + 3); //ST printf("%s\n", cpp[-1][-1] + 1);//EW return 0; }