【C语言】指针练习题目

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【C语言】指针练习题目

前言(C语言与指针,指针与题?)

提示:这里可以添加本文要记录的大概内容:

指针,是C语言的灵魂所在,而题目,是掌握指针的关键,下面通过精选几道题目,带同学深入理解指针精妙之处~


提示:以下是本篇文章正文内容,下面案例可供参考

T1:

#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;
}
//程序的结果是什么?

题解:(下面通过图文解析来刨析本题目)

答案:2,5

为了便于大家理解,特地给大家作了图为大家参考:

1.首先,代码创建了一个每个元素为int类型的,名字叫做a,的一维数组,共计5个元素

2.之后代码(取地址数组名+1)这个取地址数组名怎么理解?这是整个数组的地址,这个取地址数组名的类型是int ✳[5],加一会跳过整个数组,地址来到数字5后面的内存空间,之后再将这个地址强制类型转换为int*类型

3.最后打印:第一个✳(a+1)是数组名加1,数组名是数组首元素的地址,其类型是int类型,加一会跳过一个int类型的长度空间,来到指向数字2的地址,解引用这个指向数字2的地址,会得到数字2,同理,ptr因为被强制转换为int类型,所以str-1会跳过一个int类型大小的空间,指向数字5的空间,解引用拿到数字5

T2:

//在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;
}

答案:0x100014,0x10001,0x10004;

同样,为了便于大家理解,我们以图的形式对main函数之前的代码加以解析,再以文字的形式简单介绍一下后面的代码含义:

之后,我们再来分析main函数中的打印函数:

1.p+0x10x1是一个十六进制数字,其值还是数字1,p是一个指针变量,是一个地址,一个指针加整数,跳过多大内存取决于变量p的类型的内存大小,我们从题目中可以看到,该结构体大小为20,所以跳过20个字节,得到地址:0x100014;

2.剩下两个的话,还是同样的道理,,但是需要注意:指针p加一个数字1跳过的字节取决于p类型的大小,但是一个数字加上一个数字是几就是几… p被强转为无符号longlong类型,,属于整形类型,不是指针!!!所以跳过1个字节到答案0x10001;

3.第三个跟第一个同理,指针加整数跳过几个字节取决于p指针的类型,int是4个字节,加一就是加一个int类型大小,跳过4个字节,得到答案0x10004。

T3:

代码如下(示例):

#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

解析:

这个题目,不知道有没有同学进坑呢?以为二维数组的存储方式是这样的:

但是,因为里面是逗号表达式,小括号里面的数字取最后一个,所以是这样滴:

1.int*p;这是创建了一个指向int类型的指针变量p;

2.之后有同学就奇怪了,怎么好像把第一行给p了???我们把二维数组首元素a【0】也就等同于一维数组a【0】第一行的名称,数组名称又等同于一维数组a【0】首元素的地址,也就是把数字1的地址给了p!!!

3.我们打印的时候,p【0】可以理解为✳(p+0),所以说顺利解引用拿到了数字1并进行打印~

T4:

//假设环境是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;
}

答案:FFFFFFFC,-4

解析:

本题的主要奇怪的地方呢是,数组a是由5个一维数组int【5】组成的,但是创建变量接收的时候,变量的类型是int*【4】的类型,我们下面通过画图来进一步理解:


我们知道:

&p[4][2]可以等价于&✳(✳(p+4)+2)

&a[4][2]可以理解为&✳(✳(a+4)+2)

那么放在咱们数组中,可以得出以下图表:

1.指针减指针,得到的是两者间的元素个数,所以说呢,第二个空答案是-4(因为是小地址-大地址)

2.至于第一个空,因为要打印地址,是按照16进制形式进行打印,并且编译器先把-4转变成为补码,-4变成11111111111111111111111111111100,而对于地址没有反码补码的概念,编译器将这个-4的补码直接转换为地址,变成FFFFFFFC,并打印出来~

T5:

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

答案:10,5

解析:

我们通过画图的形式,来进一步展示本题目中的逻辑关系,请仔细看图:

为什么ptr1-1往前走一个元素大小呢?因为被强转为了int*类型; str2也是一样的道理。

T6:

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

答案:at

解析:

首先,

我们解引用pa,拿到的是a+1的内容,a+1的内容是一个地址,我们打印字符串的时候就是需要字符串首字母的地址,遇到\0停止打印,这样顺利打印at;

T7:

代码如下:

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

答案:POINT ER ST EW

解析:前面已经做过了六道指针题目,相比大家对于指针以及指针类型理解已经有了一定的认知,不妨最后一题我稍作解释,留下一部分空间供大家发挥:

总结(指针的理解)

本文以题目为切入点,举了7道典型题目,分别考究了对于指针的不同角度理解。

希望同学们对指针的理解能够有更深入的理解,加深理解~

相关文章
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
51 0
|
4天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
19 2
|
2月前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
2月前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
2月前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
2月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
2月前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
2月前
|
C语言
C语言指针(3)
C语言指针(3)
14 1
|
2月前
|
C语言
C语言指针(2)
C语言指针(2)
15 1