整理指针相关练习
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
这里收录的是相关指针的练习主要针对的是指针与sizeof之间的练习练完你对指针的理解将更进一层喔
一维数组指针练习
一维数组相关练习下面答案是多少呢为什么呢
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));
解析
int main()
{
//一维数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
//16
//a为数组名但在sizeof(数组名)表示的计算整个数组的大小
printf("%d\n", sizeof(a + 0));
//4或8
//首元素地址
printf("%d\n", sizeof(*a));
//4
//首元素解引用--第一个元素1的大小为4字节
printf("%d\n", sizeof(a + 1));
//4或8
//第二个元素的地址
printf("%d\n", sizeof(a[1]));
//4
//第二个元素24字节
printf("%d\n", sizeof(&a));
//4或8
//&数组名表示取出的是整个数组的地址地址的大小就是4或8
printf("%d\n", sizeof(*&a));
//16
//*和&抵消还是asizeof(数组名)表示计算整个数组大小
printf("%d\n", sizeof(&a + 1));
//4或8
//&a取出的是整个地址大小+1也是加上整个数组地址大小但地址大小就是4或8
printf("%d\n", sizeof(&a[0]));
//4或8
//a[0]就是 *(a+0)就是第一个元素然后再取地址就是首元素地址了
printf("%d\n", sizeof(&a[0] + 1));
//4或8
//第二个地址
return 0;
}
答案
字符数组指针练习
字符数组相关练习下面答案是多少呢为什么呢
1.
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
解析
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
//6
//sizeof(数组名)表示计算的是整个数组大小为6字节
printf("%d\n", sizeof(arr + 0));
//4或8
//这里arr+0表示首元素地址
printf("%d\n", sizeof(*arr));
//1
//这里的arr表示首元素地址*arr表示第一个元素'a'
printf("%d\n", sizeof(arr[1]));
//1
//表示第二个元素'b'
printf("%d\n", sizeof(&arr));
//4或8
//&arr表示取出的是整个数组地址但还是地址
printf("%d\n", sizeof(&arr + 1));
//4或8
//&arr表示取出的整个数组大小+1表示加上整个数组大小地址
printf("%d\n", sizeof(&arr[0] + 1));
//4或8
//第二个元素地址
printf("%d\n", strlen(arr));
//这里要注意strlen是专门用来计算字符大小的函数遇到'\0'停止而arr这个数组没有\0
//所以这个为随机值
printf("%d\n", strlen(arr + 0));
//无\0,所以为随机值
printf("%d\n", strlen(*arr));
//对首元素解引用访问的是第一个元素strlen('a')->strlen('97')---非法访问
//strlen()里面放的应该是一个地址然后strlen跟着这个地址往后找找到\0就停止了
//但这里strlen('a')里放的不是地址而是97这个数所以造成非法访问。
printf("%d\n", strlen(arr[1]));
//第二个元素strlen('b')->strlen('97')---也是非法访问。
printf("%d\n", strlen(&arr));
//&arr表示取出的是整个数组地址但不知道后面是否有\0所以还是随机值
printf("%d\n", strlen(&arr + 1));
//这里的arr表示首元素地址&首元素地址取出一个地址这个地址指向的是arr首元素地址再+1呢也不知道这个地址是啥了
//还是随机值
printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]+1第二个元素地址后面无\0为随机值。
return 0;
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
解析
int main()
{
char arr[] = "abcdef";
//这里是有\0的
printf("%d\n", sizeof(arr));
//7
//sizeof()计算整个数组大小,\0也算大小而strlen不算\0
printf("%d\n", sizeof(arr + 0));
//4或8
//首元素地址
printf("%d\n", sizeof(*arr));
//第一个元素大小 1
printf("%d\n", sizeof(arr[1]));
//第二个元素大小 1
printf("%d\n", sizeof(&arr));
//&arr取出的是整个数组的地址还是地址
printf("%d\n", sizeof(&arr + 1));
//4或8
//地址
printf("%d\n", sizeof(&arr[0] + 1));
//4或8
//第二个元素地址
printf("%d\n", strlen(arr));
//首元素地址后面有\0可以停止
//6
printf("%d\n", strlen(arr + 0));
//6
//首元素地址
printf("%d\n", strlen(*arr));
//第一个元素strlen(a)-->strlen(97)
//非法访问了
printf("%d\n", strlen(arr[1]));
//第二个元素
//非法访问
printf("%d\n", strlen(&arr));
//6
//&arr取出的是整个数组地址但&arr地址和首元素地址是一样的然后可以找到\0
printf("%d\n", strlen(&arr + 1));
//随机值
//&arr取出的是整个地址+1跳过整个数组地址不知道后面是否有\0
printf("%d\n", strlen(&arr[0] + 1));
//第二个元素地址
//5
return 0;
}
3.`
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
解析
int main()
{
char* p = "abcdef";
// p表示字符指针指向的是首元素的地址
printf("%d\n", sizeof(p));
//4或8
//计算首元素地址大小
printf("%d\n", sizeof(p + 1));
//4或8
//第二个元素地址
printf("%d\n", sizeof(*p));
//1
//第一个元素a
printf("%d\n", sizeof(p[0]));
//1
//第一个元素a
printf("%d\n", sizeof(&p));
//4或8
//&p是二级指针指向的是a的地址的地址
printf("%d\n", sizeof(&p + 1));
//4或8
//地址
printf("%d\n", sizeof(&p[0] + 1));
//4或8
//第二个元素的地址
printf("%d\n", strlen(p));
//6
//p表示首元素地址strlen直达\0停止
printf("%d\n", strlen(p + 1));
//5
//从第二个元素地址开始
//printf("%d\n", strlen(*p));
*p表示a
非法访问了
//printf("%d\n", strlen(p[0]));
非法访问
strlen(a)
printf("%d\n", strlen(&p));
//二级指针指向首元素的地址的地址
//所以为随机值
printf("%d\n", strlen(&p + 1));
//随机值
printf("%d\n", strlen(&p[0] + 1));
//第二个元素地址
//5
return 0;
}
二维数组指针练习
二维数组相关练习下面答案是多少呢为什么呢
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
解析
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
//48
//sizeof(数组名)表示计算的整个数组大小
printf("%d\n", sizeof(a[0][0]));
//4
//第一行第一个元素大小
printf("%d\n", sizeof(a[0]));
//a[0]表示第一行数组名sizeof(数组名)表示计算的是第一行数组大小
//16
printf("%d\n", sizeof(a[0] + 1));
//a[0]表示第一行数组名但没有单独放进sizeof中也没有&所以表示首元素地址首元素地址+1表示第二个元素地址
//4或8
printf("%d\n", sizeof(*(a[0] + 1)));
//4
//a[0]+1表示第一行第二个元素地址解引用访问第二个元素
printf("%d\n", sizeof(a + 1));
//a是数组名表示首元素地址表示第一行的数组地址+1表示第二行地址
//4或8
printf("%d\n", sizeof(*(a + 1)));
//16
//(a+1)表示第二行地址解引用表示整个第二行元素
printf("%d\n", sizeof(&a[0] + 1));
//a[0]表示第一行数组名&数组名表示取出的是第一行整个地址+1跳过整个第一行数组地址大小所以表示第二行地址
//4或8
printf("%d\n", sizeof(*(&a[0] + 1)));
//16
//第二行数组地址解引用
printf("%d\n", sizeof(*a));
//a数组名没有单独放进sizeof中也没有&所以表示的是首元素地址表示第一行地址
//4或8
printf("%d\n", sizeof(a[3]));
//arr[3]表示第四行数组名单独放进sizeof内部表示计算整个数组大小
// a[3]类型是int[4]----sizeof(int[4])
// 答案是16而不是越界访问
//根据类型来计算大小不会真实访问内部空间
//表达式不参与运算不进行计算
return 0;
}
练习总结
- sizeof(数组名)表示计算的整个数组大小数组名单独放进sizeof才可以
- &数组名表示取出的整个数组的地址
- 处以上两个情况其他数组名都表示首元素地址。
- sizeof内部不参与运算不进行真实的空间访问
- sizeof() 只关注占用内存空间的大小单位是字节不关心内存中放的是什么
- strlen是求字符串长度的统计的是\0之前出现的字符个数一定要找到\0才能结束所以可能存在越界访问的可能
- sizeof 是操作符 strlen是库函数
指针笔试真题
第一题考察&数组名表示什么意思
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);
//ptr是个int*类型的指针这里的&a表示取出的是整个数组的地址再+1的话表示跳过整个数组大小的地址
//(&a+1)的类型是数组指针然后这里将它强制类型转化成int *类型
printf("%d,%d", *(a + 1), *(ptr - 1));
//*a+1,这里的a表示首元素地址+1表示第二个元素地址解引用访问第二个元素2
//*ptr-1,ptr被强制类型转换成int*类型减1后就访问到最后一个元素的地址了
return 0;
}
总结
&数组名表示取出的是整个数组的地址+1表示跳过整个数组大小。
第二题考察指针加1到底加多少
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少
//已知结构体Test类型的变量大小是20个字节
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;
}
结果
解析
int main()
{
p = (struct Test*)0x100000;
printf("%p\n", p + 0x1);
//p+1取决于指针类型这个指针是结构体类型大小为20所以加1就跳过一个结构体大小20
//16进制的20为14
//0x100014
printf("%p\n", (unsigned long)p + 0x1);
//这里将p强制类型转换成无符号长整形也就变成了整数了整数加1就是简单的加减运算
//0x100001
printf("%p\n", (unsigned int*)p + 0x1);
//这里将p强制类型转换成int*类型所以p+1跳过一个整形大小也就是4个字节
//0x100004
return 0;
}
总结
指针加+1到底加几呢
指针加1跳过多少取决于指针类型
整数加一就是加1
第三题考察指针解引用访问多大空间
//环境是小段字节序存储X86
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取出的是整个数组地址+1跳过整个数组大小然后又被强制转换成int*类型
int* ptr2 = (int*)((int)a + 1);
//a表示首元素地址强制类型转换成整形这个地址+1就是整数+1然后又被强制转换成int*类型
printf("%x,%x", ptr1[-1], *ptr2);
//ptr1[-1]可以这样表示--> *(ptr-1)
//对ptr2这个指针解引用能访问多大空间呢
return 0;
}
总结
指针解引用访问多少空间也取决于指针类型要记住指针解引用是要看访问多少空间的喔不要忘记啦。
第四题考察观察逗号表达式
#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) };
//注意这个不是将012345放进数组括号里是个逗号表达式最终结果应该是{135}
//所以这个二维数组放的是135000
int* p;
p = a[0];
//a[0]表示数组第一行的数组名没有单独放进sizeof中也没有&所以表示首元素地址放进p里
printf("%d", p[0]);
//p[0]表示*(p+0),就是第一个元素 1
return 0;
}
第五题考察指针-指针表示什么意思
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;
}
结果
解析
指针-指针表示指针之间的元素个数由于低地址减去高地址所以为都为-4但注意到第一个是以%p的形式进行打印是打印地址的-4在内存中是以补码的形式进行保存-4的原码反码补码分别是
//100000000000000000000000000000100原码
//111111111111111111111111111111011反码
//111111111111111111111111111111100补码
补码直接转换成16进制形式就是
总结指针-指针表示指针之间的元素个数
第6题不同类型的指针+1表示跳过多少
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;
}
结果
解析
上面有题目和这个类似
第7题考察pa++到底指什么意思呢
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
结果
解析
总结
pa++其实是pa指向的元素进行++