大家好,我们来学习一些C语言的指针笔试题。对于C语言指针的模块想必大家都非常的头疼吧,那么我们就来就来看看一些关于C语言指针的笔试题。
首先让我们看到我们今天的第一题。
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
看到这个程序运行的结果,我们就好好地来分析下这个题。
我们看到图片,我们printf语句中的a指的是数组首元素的地址指向的就是图中1位置,a+1就代表数组中第二个元素的地址,所以我们 *(a+1)得到就是第二个元素,我们的指针指向的是图中2位置,因为&a取的是数组的地址,所以&a+1指向的就是图中2位置,ptr-1指向的就是图中3位置,所以我们 *(ptr-1)得到就是第五个元素。
我们看到下一题
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
我们看到在x86环境下打印的结果,因为我们的地址在内存中的存储是16进制,所以我们的结构体大小为20个字节,指针结构体加1,跳过一个结构体的大小,我们这里第一个打印就是16进制的20,第二个我们是无符号数的长整型所以加1就是普通加1,所以打印的结果就是00000001,最后一个我们的p是int*类型的指针,所以我们这里就是加4,所以结果就是00000004。
我们继续–>:
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);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x\n", ptr1[-1], *ptr2);
return 0;
}
我们这里依旧是ptr1指向下一组数据,也就是与数组最后一个元素相邻的数据,而打印ptr1[-1]就是ptr1向前挪一个整型也就是4个字节,所以ptr1指向的就是数组的最后一个数据,所以结果就是4。第二个它先是把数组名a强制转换成整型变量,然后再加1,然后再强制转换成整型指针!就是让ptr2指向a[0]的第二个字节,看到下图:
ptr2指向了a[0]的第二个字节由于x86平台是小端序的,小端序的存取时最低位对应低地址 ,因此将会打印出2000000。
#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;
}
我们这里p=a[0]指的是取的二维数组第一行第一个元素的地址,我们要注意括号里的是逗号表达式,逗号表达式的结果就是表达式中最后一个表达式的结果,所以原来数组中存放的值就是{1,3,5}。所以我们这里的p[0]就相当于*(p+0),也就是*p,所以打印的结果为1。
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;
}
在这里我们要知道指针减指针得到的是两个地址之间的元素个数,我们首先做出图像,我们发现&a[4][2]取的是第五行第三个元素的地址,而我们定义的*p数组指针,p=a我们就知道这单纯的把数组a的元素被p分为以四个元素为一行,所以我们的&p[4][2]就是我们刚得到的数组的第五行第三个元素的地址,所以两个相减得到-4,然而我们前面还得打印这个数的地址,那么我们首先就得知道地址是以16进制的形式存储的,我们首先得到的是-4的补码,因为负数里存储的是补码,我们给它取反加一得到原码,但我们这个时候是二进制,所以我们要给它转换成16进制,1111代表二进制的15,转换成16进制就是f,而1100代表的是二进制序列的12,所以转换成16进制就是c,所以地址就是fffffffc。
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;
}
看了前几个题相信大家对ptr1已经有了更加深刻的理解,我们的ptr1指向的就是下个数据,ptr-1指向就是这个数组最后一个元素,得到的结果就是10,我们这里的aa+1就相当于aa[1],也就是&aa[1][0],所以指向的就是二维数组第二行第一个元素,那我们的ptr2-1指向的就是第一行最后一个元素的地址,所以得到的就是5。
在今天的学习中大家一定都会有些许收货吧,我们下次见,谢谢大家。