C 二维数组,以及自定义二维数组

我们通常情况下是这样定义一个二维数组的:

int a[10][15];

我们分别查看一下 a,a[0],*a

都是一样的值吧

我们可以这么理解: a是一个数组的数组

a是数组首元素的地址,a的首元素是一个15个元素的数组,a[0]和a[0]的首元素(a[0][0])的地址是同一个地址

所以有人可能会想int **pa 是不是 跟a同一个类型的

我们可以尝试下面的代码:

int a[4][2]=0x1234;
int **ppa=a;
//尝试写入数据
**ppa=1;

我们发现段错误,说明出错了,而且ppa并不能代表a

我们把a,*a,**a,ppa,* ppa打印出来

a和ppa的值相同没问题,因为是指向同一个地址,*a仍然是a的首地址,*ppa直接解引用了

所以**ppa相当于向0x1234写入数据所以发生了段错误!

如果想理解好这个我们先看一下c语言多维数组的内存是什么样的:

实际上,在内存中,多维数组也是像一维数组一样是连续的,只不过我们把这个数组抽象了一下,

我们让这个数组的首地址赋值给一个int**指针,那么这个指针会认为是一个int*数组的地址

(就是一个数组里面保存的都是指针),所以这样解引用会发生错误

解决方法:

使用指向多维数组的指针:

int (*pa)[2];//注意和int *pa[2] 区别,后者是一个保存int*的数组

比如我们在函数传参的时候

这样会导致后面的2是固定的,编程的时候会受到一些限制

int func(int (*pa)[2],int l);

int (*p)[2]的理解:

int a[4][2];
int (*pa)[2]= a;
printf("%p\n",(char*)&pa[1]-(char*)pa);

自增一次多走了sizeof第二个维度的长度

如果是函数定义的话,也可以:

int func(int a[][2],int l)这样a第一个维度可以不是固定的,第二维度是固定的,也不是很方便,我们如果定义动态二维数组的话一般不适用多维数组,适用数组的数组

数组的数组(自定义二维数组):

就是用一个int**ppa来指向一个区域,这个区域内每一个元素都是一个指针,每一个指针都指向一个数组

const int col = 5;
const int row = 5;
int **t = (int **)malloc(col*sizeof(int*));
for(int i = 0;i<col;i++)
t[i]=(int*)malloc(row*sizeof(int));

当然,我们也可以把这些不连续的小空间放在一起申请

int **t = (int **)malloc(col*sizeof(int*));
int *p = (int*)malloc(col*row*sizeof(int));
for(int i = 0;i < col;i++)
t[i]=p+col*i;

C 二维数组,以及自定义二维数组的更多相关文章

  1. Android生成自定义二维码

    前面说过两种二维码扫描方式,现在说如何生成自定义酷炫二维码.二维码生成需要使用Google开源库Zxing,Zxing的项目地址:https://github.com/ZBar/ZBar,我们只需要里 ...

  2. PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?

    如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) { echo '是一维数组' ...

  3. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  4. [zt]C++二维数组讲解、二维数组的声明和初始化

    定义: int *pia = new int[10]; // array of 10 uninitialized ints 此 new 表达式分配了一个含有 10 个 int 型元素的数组,并返回指向 ...

  5. C++二维数组、指针、对象数组、对象指针

    项目中用到,随手记一下: 1.二维数组.与指针 创建二维数组指针的方式: a.已知一维的大小 1 int **array=new int *[rows]; 2 (for int i=0;i<ro ...

  6. 《剑指Offer》第1题(Java实现):在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

    一.题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...

  7. 剑指Offer 1. 二维数组中的查找 (数组)

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  8. 06-01 Java 二维数组格式、二维数组内存图解、二维数组操作

    二维数组格式1 /* 二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的 ...

  9. C/C++——二维数组与指针、指针数组、数组指针(行指针)、二级指针的用法

    本文转载自:https://blog.csdn.net/qq_33573235/article/details/79530792 1. 二维数组和指针 要用指针处理二维数组,首先要解决从存储的角度对二 ...

随机推荐

  1. 【Leetcode】【Easy】Same Tree

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  2. 设计模式:解释器(Interpreter)模式

    设计模式:解释器(Interpreter)模式 一.前言 这是我们23个设计模式中最后一个设计模式了,大家或许也没想到吧,竟然是编译原理上的编译器,这样说可能不对,因为编译器分为几个部分组成呢,比如词 ...

  3. DatagramSocket类 会发生线程阻塞的方法

    遇到这个问题,还告诉别人错了,这里来Mark一下. receive()方法会使调用线程阻塞. Java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是 ...

  4. 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.3.垃圾收集器与内存分配策略

    1.学习目的 当需要排查各种内存溢出. 内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. Java内存运行时区域的各个部分,其中程序计数 ...

  5. codeforces Flipping Game 题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/.未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

  6. Gluon sgd

    from mxnet import nd,autograd,init,gluon from mxnet.gluon import data as gdata,loss as gloss,nn num_ ...

  7. 池化层pooling

    from mxnet import autograd,nd from mxnet import gluon,init from mxnet.gluon import nn,loss as gloss ...

  8. PHP----练习------球队列表

    题目:页面上有一个ul球队列表当鼠标移动到某个li上的时候改行背景颜色变红,当点击某个li的时候,让该li之前的所有li背景色变黄,之后的所有li背景色变蓝.自己不变色. <!DOCTYPE h ...

  9. [19/04/05-星期五] 多线程_Thread(线程、线条)、基本术语

    一.基本概念 多线程是Java语言的重要特性,大量应用于网络编程.服务器端程序的开发,最常见的UI界面底层原理.操作系统底层原理都大量使用了多线程. 我们可以流畅的点击软件或者游戏中的各种按钮,其实, ...

  10. 【bootstrap】插件

    1.bootstrap.js 和 bootstrap.min.js 都包含了所有的插件. 2.命名空间:即域:域内成员的有效范围.超出范围就是无效. 3.通过 data 属性 API 就能使用所有的 ...