当前位置: 首页 > news >正文

C语言指针运算题

1. 题目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,并且进行了初始化。

接着,创建一个整型指针变量ptr,ptr指向地址是(&a+1)。操作符&加上数组名a,得到的是整个数组的地址,+1后会跳过整个数组,指向的是数组后的地址,不过(&a+1)的指针类型为int(*)[5],因此赋值给指针ptr时,需要进行强制类型转化。

最后,打印两个整型变量。一个为*(a+1),另一个为*(ptr-1)。

*(a+1),数组名a与整数进行加减运算,那么a代表的是数组首元素的地址,+1后跳过一个元素,即指向数组中第二个元素的地址,解引用操作后得到该元素;ptr指向的是数组后的地址,因为ptr是整型指针变量,-1后会跳过一个整型变量的大小的空间,此时指向数组中最后一个元素的地址,解引用操作得到该元素。

因此,打印结果应该为:2,5

2,5

2. 题目2

代码如下,推测程序输出结果:

#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,一共三行两列,并且进行初始化。

创建整型指针变量p,并将数组首元素地址赋值给p。

打印数组首元素。

那么关键就在于判断数组中的元素。有意思的时,这串代码在初始化数据时虽然形式上与分行初始化十分相似,但是分行初始化使用的是大括号{ },而不是圆括号( ),所以说,这里初始化数据使用的是逗号表达式,返回值位括号中最右侧的值,也就是说数组中元素实际为 1,3,5,0,0,0 

那么,输出结果应该是:1

1

我们可以将数组元素全部打印出来,判断我们的分析是否正确:

#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int i,j;for(i = 0;i < 3;i++){for(j = 0;j < 2;j++){printf("%d ",a[i][j]);}printf("\n");}return 0;
}
1 3 
5 0 
0 0 

3. 题目3

代码如下,推测程序输出结果:

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

逐层分析:

首先创建一个二维整型数组a,一共有五行五列。

然后创建一个指针变量p,类型为int(*)[4],将数组a的地址赋值给指针p。

最后分别以地址和整型打印出&p[4][2] - &a[4][2]的结果。

我们发现,a作为二维数组名,单独使用时属于指针,指向的是整个第一行a[0],类型为int(*)[5]。我们发现p与a的类型不同,因此在将a的地址赋值给p后,a+1与p+1所跳过的内存大小是不同的。a+1跳过 5 * 4 = 20个字节,而p+1则跳过 4 * 4 = 16个字节。那么a[0]一共有5个元素,p[0]一共有4个元素。

我们知道,指针-指针得到的结果是两个地址之间的元素个数。

那么&p[4][2] - &a[4][2]运算就是 (4 * 4 + 3) - (4 * 5 + 3) =  -4

所以以整型形式打印出来结果就是-4,而在以地址形式打印出来时,编译器就是会将其作为64位的无符号整数来打印(64位系统下),具体形式如下:

-4
//原码
10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100
//反码
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011
//补码
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111100
//转化为16进制的地址形式
FF FF FF FF FF FF FF FC

所以打印结果就应该是:FFFFFFFFFFFFFFFC,-4

FFFFFFFFFFFFFFFC,-4

4. 题目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;
}

逐层分析:

这题与题目1的思维类似,区别在于这里创建的是二维数组

创建二维整型数组aa并初始化,创建两个整型指针变量ptr1和ptr2,分别赋值(&aa + 1)和(*(aa + 1))。

&aa+1,aa为二维数组名,&aa得到整个数组的地址,+1后跳过整个数组,指向数组后的地址。类型为int(*)[2][5],赋值给ptr1时需要进行强制类型转换。

*(aa+1),aa为二维数组名,无操作符sizeof与&时,代表的是二维数组首行的地址,类型为int(*)[5],+1后跳过整行,指向第二行。解引用操作后得到整个第二行aa[1],类型为int *,这时赋值给ptr2时并不需要进行强制类型转换,即使使用了,也不会出现语法错误。

分析完这些后,我们开始分析打印结果。

ptr1指向的是数组后的位置,类型为int *,-1后向前跳过一个整型元素大小的空间,也就是指向二维数组最后一个元素的地址,解引用操作后得到该元素,也就是10.

ptr2指向的是第二行首元素的地址,-1后向前跳过一个元素,指向第一行最后一个元素的地址,解引用操作后得到该元素,也就是5。

所以,打印结果为:10,5

10,5

5. 题目5

代码如下,推测程序输出结果:

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

逐层分析:

首先,创建一个字符指针数组,并进行初始化,存储三个字符串首字符的地址。

然后,创建一个二级字符指针pa,并将数组a首元素的地址赋值给pa。

接着让pa自增,最后打印该字符串。

pa指向的是数组a首元素的地址,自增操作后,向后跳过一个元素,指向数组中第二个元素,即第二个字符串首字符的地址的地址。解引用操作后,得到该字符串的首字符的地址。最后打印出字符串at。

at

6. 题目6

代码如下,推测程序输出结果:

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

这题很复杂,一定要保证思路清晰:

首先,创建一级字符指针数组c,存储4个字符串首字符地址。

接着,创建二级字符指针数组cp,并存储4个一级字符指针:c+3,c+2,c+1,c

然后创建三级字符指针cpp,并将数组cp首元素地址赋值给cp

最后打印4行结果

我们逐个分析:

第一条:

**++cpp,cpp指向数组cp[0],自增操作后,指向cp[1],第一次解引用得到cp[1],即地址c+3。第二次解引用,得到c+3处的元素,即字符串"POINT"首字符地址P的地址,所以打印结果为"POINT"

第二条:

*--*++cpp+3,cpp此时指向cp[1],根据操作符优先级,先进行自增操作,此时指向cp[2],第一次解引用操作,得到cp[2],即地址c+1;接着,进行自减操作,此时,cp[2]指向c,第二次解引用操作得到c处的元素,即字符串"ENTER"首字符E的地址;+3后,向后跳过三个字符,所以打印结果为"ER"

第三条:

*cpp[-2]+3,cpp此时指向cp[2],根据操作符优先级,先进行cpp[-2]操作,可以转化为*(cpp-2),cpp-2则指向cp[0],第一次解引用得到cp[0]元素,即c+3;第二次解引用操作得到c+3处的元素,即字符串"FIRST"首字符地址;+3后向后跳过三个字符,所以打印结果未"ST"

第四条:

cpp[-1][-1]+1,此时cpp指向cp[2],根据操作符优先级,先进行cpp[-1][-1]操作,可以转化为

*(*(cpp-1)-1),从内向外,cpp-1指向cp[1],第一次解引用后得到cp[1],即地址c+2;c+2 - 1得到c+1,第二次解引用操作得到c+1处元素,即字符串"NEW"首字符"N"的地址,+1后向后跳过一个字符,所以打印结果为"EW"

POINT
ER
ST
EW
http://www.dtcms.com/a/334730.html

相关文章:

  • [Python]PTA:实验2-3-2-for 求N分之一序列前N项和
  • HTML 常用属性介绍
  • 教育的终极指向:一场精心准备的“得体退出”
  • InfluxDB 数据迁移工具:跨数据库同步方案(一)
  • 一个.NET开源、轻量级的运行耗时统计库
  • 解决 Windows 下运行 MCP 脚本弹出 WSH 错误窗口的问题 | Windows Script Host
  • vscode配置cpp运行和调试环境(保姆级)
  • 一文入门Gin框架
  • 【运维心得】三步10分钟拆装笔记本键盘
  • 【自用】JavaSE--特殊文件Properties与XML、日志技术
  • 《零基础掌握飞算Java AI:核心概念与案例解析》
  • Swift 实战:实现一个简化版的 Twitter(LeetCode 355)
  • Cohere 开发企业级大型语言模型(LLM)
  • Vue实例中的其他属性【5】
  • 安全审计-iptales防火墙设置
  • Java硬件融合实战:Vector API+ROCm加速大模型推理优化解锁AMD GPU异构算力,实现LLM本地化部署
  • Mysql常见的优化方法
  • OpenShift 4.19安装中的变化
  • 失落城堡2 送修改器(Lost Castle 2)免安装中文版
  • 安卓11 12系统修改定制化_____修改系统默认域名解析规则 实现屏蔽广告 屏蔽应用更新等功能
  • JavaScript手录17-原型
  • Java后台生成多个Excel并用Zip打包下载
  • 《AI 与数据质量的深度碰撞:颠覆传统治理模式的变革》文章提纲
  • 【C++语法】手写堆与有关堆的容器/函数
  • CMake进阶: 配置文件(configure_file)
  • 数据结构初阶(17)排序算法——非比较排序(计数排序·动图演示)、排序算法总结
  • 打卡day40
  • 在本地部署Qwen大语言模型全过程总结
  • Go语言panic机制详解
  • goland在windows上编译突然变慢