【C语言】指针、多维数组零碎知识点


🌈 关于C指针和数组 相关的东西 今天被狠狠整顿了,现在回忆整理一下相关的知识点,既作分享,也加强记忆。本blog需要有基本的指针和数组相关的知识储备

文章目录

提要

下面是学习的点。配合代码食用更佳~🌞

  1. 二维数组 存储形式和一维数组一样
  2. a2 3是左值是因为a2 3等价于 * (a+2* 4* sizeof(int)+3*sizeof(int))
  3. (int)b【也就是强制转换后】是右值,数组名a等效于右值
  4. 关于 int*c =((int *)&a);
  5. 关于 float 类型 用%d读的时候 出现的0.0000问题

1.二维数组

首先二维数组 我们知道是am n这样的形式,其实就是数组的数组,可以理解为类似于矩阵的形式。

🤔那二维数组的存储方式和一维数组一样具体怎么理解?也就是二维数组和一维数组一样,是连续的存储空间。下面用一个代码展示一下。

c 复制代码
#include<stdio.h>
int main(void){
    int a[2][3]={{1,2,3},{4,5,6}};
   
    printf("a[0]:%p\n",a[0]);
    printf("a[0][1]:%p\n",&a[0][1]);
    printf("a[0][2]:%p\n",&a[0][1]);
    printf("a[0][3]:%p\n",&a[0][3]);
    
    printf("a[1]:%p\n",&a[1]);
    printf("a[1][0]:%p\n",&a[1][0]);
    printf("a[1][1]:%p\n",&a[1][1]);

    return 0; 
}

思考一下,给出答案

也许有人会问a0 3不是越界了嘛?我的理解: 但是其实越界这个概念的提出只是因为防止在连续的存储空间内没有这个变量,或者更改了其他的变量。而在这里,也就是连续的存储空间里,a0 2下个值 在我们看来是a1 0,但其实写成a0 3也没有关系,表示的就是a0 2下个连续的地址。所以这边a1 0和a0 3是同一个东西。

答案如下~ 二维数组的存储形式 以sizeof(int) 个单位 依次递增,其存储形式表现的和一维数组是一样的形式。

c 复制代码
a[0]:0061FEFC
a[0][1]:0061FF00
a[0][2]:0061FF04
a[0][3]:0061FF08
a[1]:0061FF08
a[1][0]:0061FF08
a[1][1]:0061FF0C

关于二维数组和指针的指针

我们知道,一维数组也就是a\[\],其数组名a是该数组的首地址,而指针变量是存储地址的变量类型,所以这个数组名a也可当作指针变量使用,那么二维数组是否也有类似的形式?

🌿对于一维数组而言

c 复制代码
int d[3]={1,2,3};
int *p2=d;

printf("*(p2+1):%d\n",*(p2+1));
printf("*(p2+2):%d\n",*(p2+2));
printf("*(d+1):%d\n",*(p2+1));
printf("*(d+2):%d\n",*(p2+2));

printf("address:(p2+1):%d\n",(p2+1));
printf("address:(p2+2):%d\n",(p2+2));
printf("address:(d+1):%d\n",(d+1));
printf("address:(d+2):%d\n",(d+2));

此时答案应该显而易见。由于p是指向a的指针,也就是p存储的值是a的地址,a也可当作指针变量使用,所以他俩的地址一样,解引用后得到的值也一样。

c 复制代码
*(p2+1):2
*(p2+2):3
*(d+1):2
*(d+2):3
address:(p2+1):6422264
address:(p2+2):6422268
address:(d+1):6422264
address:(d+2):6422268

🌾对于二维数组

🤔依葫芦画瓢,那么怎么表示指向一个二维数组的指针变量,同时也可以用这个指针变量达到和类似二维数组表现形式一样的效果呢?

设有二维数组int a3 4;那么是不是也声明一个指针的指针,类似于int** p=a?

非也非也。

上文提到,二维数组存储形式和一维数组一样,二维数组的存储形式以sizeof(int) 个单位 依次递增,其存储形式表现的和一维数组是一样的形式。而int ** p是指针的指针,具体而言,p是一个指针,假设它存储的是地址A,而这个A是另一个指针变量的地址,于是用 ** 表示指针的指针。二维数组是和一维数组一样的存储形式,即顺序存储形式,也就不能用这种** p直接进行表示。

具体也可以试试看。 ** p如果指向a的地址,那么 p第一次解引用是a0 0 ,第二次解引用呢?没有地址可以给他解引用了,所以这样肯定是不行的。

指向二维数组的指针可以表示为 int (*p)4 = a;

也就是指向数组的指针,具体而言,这个p是一个指针变量,它指向int4类型的数组;p+1表示的是 从基地址a0 0 开始向下偏移1个单元,这一个单元包含4个int变量,也就是4个sizeof(int);二维数组a3 4可以看作是含有3个单元,其中这的每个单元含有4个int类型的变量。所以总共有3 *4 个sizeof(int)

c 复制代码
	int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
    int (*p1)[4]=a;
    
	printf("p1:%p\n",p1);
    printf("a:%p\n",a);
    printf("a[0][0]:%p\n",&a[0][0]);
    printf("------------------\n");

    printf("p1+1:%p\n",p1+1);
    printf("a+1:%p\n",a+1);
    printf("a[0][4]:%p\n",&a[0][4]);
    printf("------------------\n");

    printf("p1+2:%p\n",p1+2);
    printf("a+2:%p\n",a+2);
    printf("a[1][4]:%p\n",&a[1][4]);
    printf("------------------\n");

    printf("*(p1+1):%p\n",*(p1+1));
    printf("*(a+1):%p\n",*(a+1));
    printf("a[1][0]:%p\n",a[1]);
    printf("------------------\n");

    printf("*(*(p1+1)+1):%d\n",*(*(p1+1)+1));
    printf("a[1][1]:%d\n",a[1][1]);

答案如下~记得自己多敲几遍。

c 复制代码
p1:0061FEE8
a:0061FEE8
a[0][0]:0061FEE8
------------------
p1+1:0061FEF8
a+1:0061FEF8
a[0][4]:0061FEF8
------------------
p1+2:0061FF08
a+2:0061FF08
a[1][4]:0061FF08
------------------
*(p1+1):0061FEF8
*(a+1):0061FEF8
a[1][0]:0061FEF8
------------------
*(*(p1+1)+1):5
a[1][1]:5

2. int*c =((int *)&a);

c 复制代码
int a=9;
int *p3=(int*)&a;

printf("*p3:%d\n",*p3);
printf("address: p3 :%p\n",p3);
printf("address: a :%p\n",&a);
printf("==============================\n");

第二行:这句话的意思是把a转换为一个int*的指针,这个指针变量存储的是3,这个变量的地址还是 a的地址。最后赋值给c


结果

c 复制代码
*p3:9
address: p3 :0061FED4
address: a :0061FED4

3. float 类型 用%d读 出现的0.0000问题

一切从一个程序说起,还是有点坑的

c 复制代码
#include<stdio.h>
int main(void){
    float a=999897.777;
    int b=a;
    printf("%d,%f,%d,%f\n",b,a,a,b);
    return 0; 
}

🤔仔细想想最后输出什么;


c 复制代码
999897,999897.750000,-2147483648,0.000000

这段代码其实比较基础。

首先,前面几个不难得到。

c 复制代码
int b=a; 

进行了一次隐式的转换,也就相当于int b=(int) a ,所以此时b=3;

前面的第一个b 和 a不疑惑。第三个值,a等于一个负值,其实也不难理解,由于浮点数存储的形式和整型是不一样的,所以它读到的整形变量上是一个赋值不奇怪。

最后一个0.00000就比较难理解了,需要和底层硬件联系起来。

🐳具体解答可以看看这篇blog

总结一下就是 由于float 和 int 存储形式的差异,导致最终的结果为0;

flaot 存储的形式是 类似 整数+指数 这样的类型的,比如312.2怎么存储的?就是把3122放入整数中,然后指数为-1,也就类似于3122* 10(-1) 这样存储的 。
🌈 ok 完结~

相关推荐
c++之路18 分钟前
C/C++ 全链路编译工具汇总
c语言·开发语言·c++
c2385619 分钟前
C++的IO流深入理解(下)
开发语言·c++
某林21228 分钟前
ROS 2 与大模型融合实战:从进程连环崩溃到类型安全防御的深度排障复盘
c++·python·安全·机器人·人机交互·ros2
凡人叶枫32 分钟前
Effective C++ 条款02:宁可以编译器替换预处理器
java·linux·c语言·开发语言·c++
AC赳赳老秦1 小时前
用 OpenClaw 制定技术学习计划:根据目标岗位自动生成学习路线、推荐学习资源
开发语言·c++·人工智能·python·mysql·php·openclaw
周杰伦fans1 小时前
AutoCAD2016经典模式不见了-设置回14版本前的经典工作空间
服务器·c语言·前端
ShineWinsu1 小时前
对于Linux:内核是如何组织管理IPC资源的解析
linux·服务器·c++·面试·笔试·线程·ipc
少司府2 小时前
C++进阶:红黑树
开发语言·数据结构·c++·b树·二叉树·红黑树
caimouse2 小时前
Reactos 第 5 章 进程与线程 — 5.1 概述
c语言·windows·架构
汉克老师2 小时前
GESP6级C++考试语法知识(五十五、动态规划----背包问题(八、混合背包)
c++·动态规划·dp·背包问题·gesp六级·混合背包问题