今天总结分享几个关于C语言指针方面的一些笔试题,主要是对前些日子练习的一些总结,同样也希望看到这篇文章的人,对你能有所帮助。如果有错误的部分,也希望即使指正
笔试题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;
}`
程序的运行结果是什么
首先,从这段代码中可以看到定义了一个长度为5的数组a,然后定义了一个指针ptr,将
ptr指向(int*)(&a+1),(&a+1)数组名取地址再加1,是跳过整个数组,指向a[4]
后面的地址,(int*)再将int(*)[5]类型的变量强转为int(*)类型,然后打印
*(a+1),数组名加1,在C语言中a将强制转换为a[0]的地址意味着数组的首元素地址向
后跳过一个元素即为a[1]的地址,在解引用打印数字为2,*(ptr-1)则是将ptr指针向前
跳过sizeof(int)个字节,在解引用,于是打印的结果回事a[4]中的数值,也就是5,
于是此题的答案则为2,5
笔试题2.
struct Test
{
int Num;
char *pcName;
shortsDate;
char cha[2];
shortsBa[4];
}*p;
假设p 的值为0x100000。 如下表表达式的值分别为多少?
p + 0x1 = 0x___ ?
(unsigned long)p + 0x1 = 0x___ ?
(unsigned int*)p + 0x1 = 0x___ ?
题中的代码给出一个结构体,并定义了一个指向该结构体的指针p,p+0x1,可以理解为p+1
因为0x1本就是16进制中的1,指针加1就等于指针向后跳过指针所指向类型的字节数,这里
根据结构体中的内容可知此结构体大小为20个字节,所以p+0x1 = 0x100020,
(unsigned long)p + 0x1这里是将p强制转换为unsigned long类型,再加一,就得到
一个unsigned long类型的整数,用16进制表示为0x100001
(unsigned int*)p + 0x1最后一个问题是将p强制转换为unsigned int*类型的变量,
再加1,指针加一就跳过sizeof(unsigned int*)个字节,也就是4个字节,这里答案为
0x100004
面试题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;
}
//求程序运行结果
题中首先定义了一个长度为4的int类型的数组,ptr1指针指向(int*)(&a+1),&a+1
跳过整个数组指向a[3]之后的地址,再转为int*类型。所以ptr1[-1]应该得到的打印结果
为a[3]处的结果,0x4
ptr2指向(int*)((int)a+1),首先将a[0]处的指针强转成int型,+1之后向后跳过一个
字节,之后再转为int*类型,打印时,*ptr2读取4个字节,若为小端字节序存储,则打印
结果为0x2000000,若为大端字节序,则为0x100
面试题4.
int main(int argc, char * argv[])
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
}
//求程序运行结果
这个题应属于细节类题目,从代码中可以看到,二维数组a[3][2]初始化时内部用了
(),复制结果()内部转换成逗号表达式,导致只初始化了前三个数据,之后定义了
一个指针p指向a[0],打印p[0]也就是a[0][0]应该得出的结果是1
笔试题 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;
}
//求程序运行结果
首先这个题定义了一个int类型的二维数组,和一个长度为4的数组指针,p指向二维数
组,由于两个变量类型不相同,C语言编译过程中发生了强制类型转换,又因为数组在内
存中的分布是呈线性排列,
这里借用一张图来解释一下p在内存中的分布,照此推理,p[4][2]也就指向的 是a[3][3],&p[4][2] - &a[4][2]之间相差4个元素,所以打印出来分别就是16进制的-4,和十进制的-4
笔试题 6.
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));
//求程序运行结果
这个题目定义了一个int型的二维数组aa,长度为2,定义了两个指针ptr1和ptr2,
ptr1指向(int *)(&aa + 1),首先前面提到过(&aa + 1)是跳过整个数组,所以
ptr1指向aa[1][4]后面的位置,ptr2指向(int *)(*(aa + 1)),aa + 1首先
需要给aa解引用,之后再加1,解引用完之后aa的类型应该是int(*)[5],+1后指向
的位置应该是aa[1][0]处,ptr1 && ptr2 都是int*类型,所以最后打印的结果
应该是在原位置向前跳过一个int类型,答案为10,5
笔试题 7.
char *a[] = { "work","at","alibaba" };
char**pa = a;
pa++;
printf("%s\n", *pa);
//求程序运行结果
这个题首先定义了一个char(*)[]类型的变量a,指向"work","at","alibaba",接着又定义了一
个char** 类型的指针pa指向a,pa++也就是pa解引用后+1,pa就指向了at字符串的首地址,所以
打印结果为at
笔试题 8.
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);
这个题定义了三个指针,char[]类型的一阶,二阶各一个,char类型的三阶指针一个,一阶指
针c指向"ENTER","NEW","POINT","FIRST",二阶指针cp指向c + 3,c + 2,c + 1,c,
三阶指针cpp指向cp,
第一个打印首先++cpp,就是将cpp解引用+1,也就是cp+1,指向cp[1]再连续解引用,打印得到
"POINT"
第二个打印,首先算单目运算符++cpp,同上可得cp+1,指向cp[2],解引用再--,指向c[0],继续
解引用+3,打印结果为"ER"
第三个打印cpp[-2],首先解引用,得到cp[2],再-2,得到cp[0],接着解引用得到c[3] +3,打印
结果为"ST"
第四个打印cpp[-1]解引用-1,得到cp[1],重复[-1],得到c[1]再+1,指向"NEW"的"E",打印结
果为"EW"