C语言-八道题深入理解c指针
Posted 4nc414g0n
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言-八道题深入理解c指针相关的知识,希望对你有一定的参考价值。
八道题深入理解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;
}
结果是2,5
解释:
&a + 1,由于&与数组名结合&a表示整个数组&a + 1指向数组尾
由于&a+1的类型是int*[5]所以类型转换为int*
由于ptr为int*, ptr - 1即向前4个字节指向元素5
2. 第二题
假设p 的值为0x100000。 如下表表达式的值分别为多少?
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
printf("%p\\n", p + 0x1);
printf("%p\\n", (unsigned long)p + 0x1);
printf("%p\\n", (unsigned int*)p + 0x1);
return 0;
}
分别是0x100014,0x100001,0x100004
解释:
- 0x1就是16进制的1,p指向的结构体的大小是20个字节,p+1即0x100000加16进制的20及0x100014
- (unsigned long)p,强转为unsigned long后加0x1就看作十进制加1即为0x100001
- (unsigned int*)p,强转为unsigned int*后加0x1就是跳过一个无符号整形变量即加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,2000000
解释:
- ptr1参考题一
- ptr2: a指向第一个元素被强转为int后如图绿色部分之后在被强转为int*赋给ptr2,并且一个字节一个地址,也就是0x0012ff44和0x0012ff45差一个字节
- 打印时按照%x打印,从高地址处取ptr2为0x02000000
ptr1[-1] == *(ptr1-1),ptr1为0x00000004
而%x只会从有效数字开始打印,即打印4,2000000
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
解释:注意!!!: a[3][2]花括号内是三个逗号表达式,相当于a[3][2]={1,3,5};
- 此二维数组相当于{{1,3},{5,0},{0,0}}
- 未与sizeof或&结合,a[0]为二维数组的首元素也就是第一行数组的数组名,也就是第一行数组首元素1的地址
- p[0] == *(p+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;
}
结果为FFFFFFFC,-4
解释:
- p类型为int(*)[4],而a第一行是五个整形的数组,作为地址类型应该是int(*)[5],p+1只能向后访问4个元素,而a+1可以访问5个
- p[4] == *(p+4)即图中p+4向后取4个元素,&p[4][2]表示第五行第三个元素地址,如图,&p[4][2] - &a[4][2]表示相差元素个数由于&p[4][2]地址比&a[4][2]地址小,为-4
- -4原码1000000000000000000000000000100
反码:11111111111111111111111111111111011
补码:11111111111111111111111111111111100
按照%p格式打印就将补码看作地址:FFFFFFFC
按照%d格式打印要回到原码:-4
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;
}
结果是10, 5
解释:
- ptr1指向二维数组尾部
- *(aa+1) == aa[1],指向元素6, 本来就是(int*)类型
- 即*(ptr1 - 1),和*(ptr2 - 1)都是打印向前一个字节的元素
7. 第七题
程序运行结果是什么?
#include <stdio.h>
int main()
{
char* a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\\n", *pa);
return 0;
}
结果是 at
解释:
- char* a[] = {“work”,“at”,“alibaba”},代表一个数组每个元素是char*分别存放的是后面字符串首字母的地址
- pa存放char*地址,应为二级指针。pa++指向a数组第二个元素,即打印at
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;
}
打印 POINT ER ST EW
解释:
- 第一次如图所示++cpp再**解引用两次打印POINT
- 第二次cpp在第一次的基础上++指向c+1,*解引用指向c数组的第二个元素,再–1,cp中第三个元素由c+1变为c,指向c数组的第一个元素,最后+3即打印ER
- 第三次cpp[-2] == *(cpp-2),再*解引用最后+3 打印ST
- 第四次cpp[-1][-1] == *(*(cpp-1)-1),先指向cp数组中的c+2再-1后变为c+1再解引用,最后+1打印EW
以上是关于C语言-八道题深入理解c指针的主要内容,如果未能解决你的问题,请参考以下文章