指针习题练习

简介: 指针习题练习

知识点复习


做题之前复习一个知识点——数组名的理解

数组名代表该数组首元素的地址,但是有两个例外:

1> &数组名,数组名代表整个数组的地址;

2> sizeof(数组名),数组名代表整个数组地地址;


开始练习吧!

题目1


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

分析 :


a表示数组首元素的地址,a+1表示跳过一个整形的大小,*(a+1)表示指向这个地址的值,也就是2

&a 表示一个数组的地址,&a+1表示跳过一个数组的大小,然后(&a+1)强制转化成int*类型,让ptr接收,那么ptr-1表示向后跳过一个整形的大小,*(ptr-1)表示指向这个地址的值,也就是5.


图解:



代码运行结果:



题目2


//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{
    int Num;
    char* pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
    printf("%p\n", p + 0x1);
    printf("%p\n", (unsigned long)p + 0x1);
    printf("%p\n", (unsigned int*)p + 0x1);
    return 0;
}

分析:

我们知道结构体大小是20个字节(题上说的),定义一个结构体指针 pp里面放的是0x100000


因为p是结构体指针,并且结构体大小是20个字节,所以p+0x1表示跳过一个结构体的大小,也就是跳过20个字节,然后%p打印地址;


(unsigned long)p表示p是一个无符号长整形,p+1就是简单的+1,但这里用的%p打印,会出现警告,但这不影响,我们主要是理解指针加减的运算,先不用管它;


(unsigned int*)p表示将一个结构体指针转化成无符号整形指针,p+0x1表示跳过一个无符号整形的大小,也就是4个字节,然后%p打印地址;


图解:



代码运行结果:



题目3

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


分析:

一个二维数组 a ,注意给数组赋值是用的逗号表达式,(逗号表达式取最后一个逗号后面的值),

所以数组里面的值是 1,3,5,0,0,0

p 指向 a[0] ,也就是二维数组的首元素,p[0]表示*(p+0),这里的 p 表示一维数组的数组名,也就是一维数组首元素的地址,也就是1的地址,*(p+0)其实就是1。


图解:



代码运行结果:



题目4


// 假设环境是 x86 环境,程序输出的结果是啥?
# 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 ;
}


分析:

int(*p)[4] 是一个数组指针,指向的数组有4int类型的元素,将a赋值给p,但是类型有一些不一样,会出现警告,但我们就是要赋值给p,别问,问就是这么强横(还不是为了刁难你,该死的出题人),a表示二维数组的首元素的地址,也就是a[0]

p[4]表示*(p+4),这里的p表示指向一个有4个整形的数组的地址,p[4][2]表示*(p[4]+2),这里的p[4]

表示一个有4个整形的数组的数组名,也就是数组的首地址,p[4]+2表示跳过2个整形的大小,   &p[4][2] - &a[4][2]这个我们看图就很好理解了,指针相减的绝对值表示相差元素的个数


图解:



代码运行结果:



题目5

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

分析:


&aa指的是整个二维数组的地址,&aa+1指的是跳过一个二维数组的大小,

&aa+1转化成int*类型,让ptr1接收,ptr1-1指的是向后跳过一个整型指针的大小*(ptr1-1)就是10

aa表示二维数组的首元素的地址也就是aa[0]aa+1指的是跳过一个一维数组的大小,然后解引用相当于aa[1]

aa[1]转化成(int*)类型,让ptr2接收,prt2-1指的是向后跳过一个整形的大小,最后解引用*(ptr2-1),就是5


图解:



代码运行结果:  



题目6

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

分析:


a是一个char类型的指针数组,放有三段字符串,

char*  *pa=a;

pa 是一个指向char* 类型的指针,a相当于数组的首元素的地址

pa++;相当于跳过一个字符串,//类似于二维数组

此时pa指向第二个字符串的首地址,对 pa  解引用,

相当于得到的是 ’a‘ ,用 %s 打印字符串,遇到 \0 停止


图解:



代码运行结果:



题目7(较难)


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

分析1:


printf("%s\n", **++cpp);

++cpp,相当于 cpp  跳过一个 char** ,指向下标为1,也就是c+2的地址

*(c+2) 解引用后表示 c+2指向的下标为2的char*类型的地址,

**(c+2) 解引用相当于 P , %s 打印字符串

结果就是:POINT

看图很容易理解,一次指针加法运算,两次解引用


图解1:



分析2:


printf("%s\n", *-- * ++cpp   + 3);在上一条语句运行的前提下,++cpp再跳过一个char**,指向下标为2,也就是c+1的地址,

*(++cpp)解引用后表示c+1,然后 --(c+1) , c+1 指向下标为1char* 类型的地址,--(c+1)相当于

指向下标为0char* 类型的地址,*(--(c+1)) 解引用后相当于E,最后在加3,跳过3个整形大小,用%s打印,

结果是:ER

比较绕,可以结合图解多看几遍,更容易理解。

图解2:



分析3:


printf("%s\n", *cpp[-2] + 3);

在前两条语句运行的前提下,cpp此时指向下标为2的地址

cpp[-2] 等价于*(cpp-2),解引用后相当于 c+3 , c+3 指向下标为3的char*类型的地址,

也就是F的地址,最后加3,跳过3个整形大小,%s打印,

结果是:ST

图解3:



分析4:


printf("%s\n", cpp[-1][-1] + 1);

在前三条语句运行的前提下,cpp此时依然指向下标为2的地址,因为在上一条printf语句中

cpp没有做运算

cpp[-1]等价于*(cpp-1),解引用后相当于 c+2, c+2 指向下标为2char* 类型的地址,

c+2[-1] 等价于*((c+2)-1), 解引用相当于指向下标为1的元素,也就是N,

最后加1,跳过1个整形大小,%s打印,

结果是:EW


图解4:



代码运行结果:



 制作不易,希望给你带来帮助!

相关文章
|
7月前
C进阶:指针的练习(1)
C进阶:指针的练习(1)
|
C++
关于指针,你不可以错过的练习(c/c++)
关于指针,你不可以错过的练习(c/c++)
62 0
|
6月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
7月前
|
C语言
C语言指针——练习
C语言指针——练习
|
7月前
入门后指针进阶习题深度分析
入门后指针进阶习题深度分析
43 1
|
7月前
|
人工智能 C++
指针习题笔记(较难,可用于思维锻炼)
指针习题笔记(较难,可用于思维锻炼)
36 4
|
7月前
指针应用基础练习
指针应用基础练习
43 0
|
7月前
|
存储 人工智能
指针的应用练习(数组与指针的关系)
指针的应用练习(数组与指针的关系)
50 0
|
C语言 C++
【C语言进阶】 指针强化练习(二)
【C语言进阶】 指针强化练习(二)
67 0
|
7月前
|
存储 搜索推荐
【C/PTA】指针专项练习(二)
【C/PTA】指针专项练习(二)
225 0