有关指针的笔试题

#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;
}

该段代码输出的结果为2和5
分析:&a得到了整个数组的地址,然后+1,跳过了整个数组,位置来到了5的后面,然后(int *)将其强制转换成整形指针的类型,只是将类型转换了,值并没有发生任何的变化,再将其赋给ptr,ptr是一个整形的指针,所以 *(ptr-1)就是将ptr想左边挪动四个字节(int *类型)的大小,来到5的地址,然后再解引用,就得到了5的值,所以输出的第二个值为5.
*(a+1)这里的a没有任何特殊的意义,就表示的是首元素的地址,a+1来到了第二个元素2的地址,然后再进行解引用的操作,就得到了2的值。

#include<stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//结构体的大小为20
//假设p的值为0x100000
int main()
{
	p=struct Test*0x100000
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

考点:指针加一
分析:首先,这个结构体的大小是20个字节,p为结构体的指针类型,所以进行一下强制类型转换,0x1的大小的值就为1。
所以打印的第一个 打印的是p+1的结果,类型又是结构体类型,那么就直接进行加法,又因为结构体的大小为20个字节,20用16进制表示的结果就是14,所以p+1的结果为0x100014
第二个打印,把p的类型强制转换为unsigned long类型,long是长整形,所以也直接进行加法就可以了,p+1的值也就为0x100001
第三个打印,把p的类型强制转换成unsigned int 类型 ,int的类型的大小为4个字节,所以p+1的值就为0x100004

#include<stdio.h>
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和2000000
分析:首先&a取到的是整个数组的地址,整个数组的地址+1,就是跳过了整个数组,来到了4的后面,再把它强制转换成(int )类型,只是改变了类型,但是他的值并没有发生任何的改变,再把它赋给ptr1,ptr1[-1]就相当于*(ptr-1),那么就来到了4的地址出,再去解引用,就得到了4的值,所以第一个输出的值是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;
}

这个题输出的结果为1;
考点:逗号表达式
分析:这个题的陷阱就在于,他对于数组的初始化,并不是用的花括号,而是用的圆括号,这就涉及到了逗号表达式的应用 ,所以初始化结束之后的数组应该为 1,3,5,0,0,0 ; a[0]得到的就是数组第一行的元素,将其赋值给p,打印p[0],那么就打印的是第一个元素1

#include<stdio.h>
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;
}

在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
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;
}

这个题输出的结果是10 和 5
分析:&aa取到的是整个数组的地址,它加1跳过了整个数组,来到了10 的后面,与上面的题一个道理,只是改变了类型,值并没有发生实质性的变化,然后将其减1再解引用,就得到了10 的值,所以输出10
第二个aa没有取地址,就得到数组首元素的地址,也就是得到了数组第一行的地址,然后加一,就得到了数组第二行的地址,在进行解引用,就得到了第二行的元素,再将其强制类型转换成int *类型,赋值给ptr2,然后ptr2-1,再解引用,就是6-1,得到了5.
所以输出的结果是10和5。

#include<stdio.h>
int main()
{
	const char* a[] = { "work","at","alibaba" };
	char** pa = &a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

这道题输出的结果是at
分析:a为指针数组,是把字符出首地址放进去了,字符串中由三个,分别是work at alibaba ,把每个字符串的首地址存放起来,放在数组中,起名字称为a,char *中分别存放的是w,a,a的地址,pa中放置的是char *的地址,pa指向的是char * 加以,所以打印的是at

发布了39 篇原创文章 · 获赞 37 · 访问量 1976

猜你喜欢

转载自blog.csdn.net/weixin_43831728/article/details/102701133