C语言指针相关练习题

C语言指针相关练习题

文章目录

  • C语言指针相关练习题
    • 题目一
    • 题目二
    • 题目三
    • 题目四
    • 题目五
    • 题目六
    • 题目七

题目一

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

第一题来说是比较简单的,先来看看代码运行结果
在这里插入图片描述

数组名的理解

  1. sizeof(数组名) 计算的是整个数组的大小
  2. &数组名 取出的是整个数组的地址
  3. 除上面两种情况,数组名都指数组的首元素地址

有了对数组名的理解,这题就好做了
&a+1 取出数组的地址然后+1,指跳过这个数组,指向数组之后的空间
数组地址应存放在数组指针中,int (*p)[ 5 ]中,强制类型转换成 int *类型存放在int *类型的指针中
无论什么类型的指针都可以存放任意类型的地址
*(a + 1) a是首元素的地址,+1指向第二个元素,解引用得到第二个元素 2
*(ptr - 1) ptr存放的是数组+1之后的地址,指向数组之后,-1之后指向数组中最后一个元素 5

题目二

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
#include <stdio.h>
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;
}

代码运行结果如下:
在这里插入图片描述

printf("%p\n", p + 0x1);

%p打印的是地址,0x1表示16进制,也就是1,指针加整数跳过多少字节的空间取决于指针的类型,在上述代码中p是结构体指针,同时题目给的结构体为20个字节,所以p + 0x1 跳过了20个字节,也就是 100014,%p打印的是十六进制的,所以是01000014

printf("%p\n", (unsigned long)p + 0x1);

在上述代码中将p的类型从结构体指针强制类型转换成了unsigned int类型,即无符号整型,p + 0x1也就变成了整数之间的加减,100001,由于是以十六进制的方式打印的,所以是00100001

printf("%p\n", (unsigned int*)p + 0x1);

在上述代码中将p的类型从结构体指针强制类型转换成了unsigned int*类型,是无符号整型指针,指针加减整数取决与类型的大小,unsigned int是4个字节的,所以p + 0x1 跳过了4个字节,也就是100004,由于打印的是十六进制的,所以是00100004

题目三

#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,3,5
在这里插入图片描述
然后定义了一个整型指针指向二维数组的首元素,然后跳过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;
}

代码运行结果如下:
在这里插入图片描述
指针数组(*p)[4]是指向数组中4个int类型的元素,数组a[5][5]的地址要存到int (*ptr) [5] 这样的数组指针中去,
两者存在着类型差异,但是不影响,a数组每四个元素存到p中去,二维数组是连续存放的,示意图如下:
在这里插入图片描述

&p[4][2] - &a[4][2] 也就是指针 - 指针 的绝对值计算的是两个地址之间的元素个数
所以得到 -4
%p打印的是地址,地址在内存中是补码的形式 十六进制打印
所以我们要将-4转化为二级制的补码
-4的原码1000 0000 0000 0000 0000 0000 0000 0100
-4的反码1111 1111 1111 1111 1111 1111 1011
-4的反码1111 1111 1111 1111 1111 1111 1100
每四个二级制位转换为
FF FF FF FC

%d打印的整型,也就是 -4

题目五

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

代码运行结果如下:
在这里插入图片描述
(int*)(&aa + 1) 是取出数组的地址然后+1,跳过整个数组,指向数组之后的空间,然后将其强制类型转换为int类型存放到ptr1中
(int
)(*(aa + 1))是数组首元素地址+1,二维数组的首元素是a[0],也就是第一行的元素,得到aa[1][0]的地址,然后解引用再强制类型转换,存放到ptr2中
所以ptr1指向的是数组之后的空间,ptr2指向的是数组aa[1][0]
与题目一致
*(ptr1-1) ptr1 - 1 指向的是10这个元素的地址,然后解引用得到10
*(ptr2-1) ptr2 - 1 指向的是5这个元素的地址,然后解引用得到5

题目六

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

代码运行结果如下:
在这里插入图片描述
a[]是个指针数组,存放的是三个字符串的地址,pa指向a的首元素地址,示意图如下:
在这里插入图片描述
pa++,指针偏移一个字节,得到第二个元素的地址,也就是 at
所以打印的是 at

题目七

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

代码运行结果如下:
在这里插入图片描述
代码示意图如下:
在这里插入图片描述

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

一开始cpp是指向cp的首元素的,当使用++之后cpp指向了cp的第二个元素,也就是c+2的地址
然后第一次解引用拿到了c+2,
再解引用得到c的第三个元素,所以会打印POINT
现在cpp指向cp的第二个元素

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

由于加法的优先级最低,使用+3最后计算
++cpp,cpp从指向cp的第二个元素变成了指向第三个元素
解引用拿到了cp第三个元素c+1
然后再–c+1得到c这个地址
解引用就得到c 也就是c的首元素ENTER
最后+3 从第四个字符开始打印
所以会打印ER
现在cpp指向cp的第三个元素

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

cpp[-2] 等价于 *( *(cpp-2))+3
cpp-2,cpp从指向第三个元素变成了指向第一个元素
第一次解引用得到 c+3
第二次解引用得到了c+3指向的元素 也就是FIRST
最后再+3 从这个元素的第四个字符开始打印
所以会打印ST
现在cpp还是指向第三个元素

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

cpp[-1][-1]+1 等价于 *( *(cpp-1)-1)+1
cpp-1 cpp从指向cp第三个元素变成指向了第二个元素
然后解引用得到c+2
然后再减去1 c+2-1
然后解引用得到了c+1 也就是NEW
最后再+1 从第二个字符开始打印
所以会打印EW

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/208770.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 问题 怎么在C++11标准语法中调用C++20的类

一. 问题 在工作中,因为一个算法功能需要跟别的部门对接,他们提供了该算法的头文件.h,静态库.lib,动态库.dll。但是头文件中使用了C++20才有的新特性,如#include等,而本地使用的vs2015开发环境,只支持C++11标准语法,这种情况下,该怎么把该算法集成到本地项目中呢? …

PCIE链路训练-状态机描述1

状态机描述 Config.linkwidth.start&#xff1a; 1. &#xff08;1&#xff09;Linkup 0 状态机没有执行链路宽度的升级&#xff08;upconfiguration of the Link width&#xff09;&#xff1a;那么tx会在所有active的dsp上发送TS1&#xff0c;其中link num为具体内容&a…

看不惯AI版权作品被白嫖!Stability AI副总裁选择了辞职,曾领导开发Stable Audio

近日&#xff0c;OpenAI的各种大瓜真是让人吃麻了。 而就在Sam Altmam被开除前两天&#xff0c;可能没太多人注意到Stability AI副总裁Newton—Rex因看不惯StabilityAI在版权保护上的行为选择辞职一事。 大模型研究测试传送门 GPT-4传送门&#xff08;免墙&#xff0c;可直接…

android11 申请所有文件访问权限

Android 11 引入了强制执行分区存储的限制&#xff0c;导致应用默认不能访问外部文件。 针对以前涉及较多文件的操作&#xff0c;可采用申请所有文件访问权限的方式来解决这一问题&#xff0c;实现方式如下。 &#xff08;虽然这样做安全性低&#xff0c;官方并不推荐这样&…

druid keepAlive 导致数据库连接数飙升

一.背景 应用在执行完某个复杂业务&#xff0c;主要包含20几个查询SQL的操作后&#xff0c;会导致数据库连接池一直升高 druid版本&#xff1a;1.2.11 druid配置文件&#xff1a; spring.datasource.druid.maxActive100 spring.datasource.druid.initialSize20 spring.datas…

一条命令彻底卸载Linux自带多个版本jdk

一条命令彻底卸载Linux自带多个版本jdk 检查系统已经安装的jdk rpm -qa | grep java卸载所有已经安装的 jdk xargs 将参数逐个传递 将已安装的 java 程序逐个当做参数传递给 rpm -e --nodeps rpm -qa | grep java | xargs rpm -e --nodeps再次检查系统已经安装的jdk rpm -qa | …

机器视觉公司为什么宁愿高薪招新人,也不愿加薪留老员工?老员工特殊时间特殊照顾,新人必须常照顾

​职场常出现的“薪酬倒挂”现象。其实这是正常的职场规律&#xff0c;实际上是企业管理不得不面对的一种选择。 很多企业宁愿老员工离职也不加薪&#xff0c;却高薪请新员工&#xff1f;这就是职场上的鲶鱼效应&#xff0c;一些高层领导认为一个企业&#xff0c;老员工好比沙…

【docker】docker总结

一、Docker简介 Docker是开源应用容器引擎&#xff0c;轻量级容器技术。基于Go语言&#xff0c;并遵循Apache2.0协议开源Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux系统上&#xff0c;也可以实现虚拟化容…

【Linux】权限的理解和使用

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Rust并发编程:理解线程与并发

大家好&#xff01;我是lincyang。 今天我们来深入探讨Rust中的并发编程&#xff0c;特别是线程的使用和并发的基本概念。 Rust中的线程 Rust使用线程来实现并发。线程是操作系统可以同时运行的最小指令集。在Rust中&#xff0c;创建线程非常简单&#xff0c;但与此同时&…

SpringBoot:kaptcha生成验证码

GitHub项目地址&#xff1a;GitHub - penggle/kaptcha: kaptcha - A kaptcha generation engine. kaptcha介绍 kaptcha官网&#xff08;Google Code Archive - Long-term storage for Google Code Project Hosting.&#xff09;对其介绍如下&#xff0c; kaptcha十分易于安装…

陪玩圈子系统APP小程序H5,详细介绍,源码交付,支持二开!

陪玩圈子系统&#xff0c;页面展示&#xff0c;源码交付&#xff0c;支持二开&#xff01; 陪玩后端下载地址&#xff1a;电竞开黑陪玩系统小程序&#xff0c;APP&#xff0c;H5: 本系统是集齐开黑&#xff0c;陪玩&#xff0c;陪聊于一体的专业APP&#xff0c;小程序&#xff…