二维数组

c语言按照行主序存储二维数组。也就是说,二维数组元素在内存中的位置是连续的,每行末尾元素(若不是最后一行)的下一个元素就是下一行的首元素。

如下图所示

接下来我们来分析一下如何将二维数组所有元素初始化零。

假设数组的声明如下:

int a[NUM_ROWS][NUM_COLS];

普通的写法是利用两层for循环

int row, col;
for (row = 0; row < NUM_ROWS; row++)
for (col = 0; col < NUM_COLS; col++)
a[row][col] = 0;

我们可以利用指针操作,将二维数组看成一个一维的大数组,其元素数量为NUM_ROWS*NUM_COLS,利用一个for循环完成操作

int *p;
for (p = &a[0][0]; p <= &a[NUM_ROWS-1][NUM_COLS-1]; p++)
*p = 0;

不过虽然代码量减少了,但实际上程序运行的次数和前者两层for循环操作运行次数是一样的。(这类方法明显破坏了程序的可读性,但是至少对一些老的编译器来说这种方法在效率方面进行了补偿。不过,对许多现代的编译器来说,这样所获得的速度优势往往极少甚至完全没有。)

接下来我们再看一个例子:将二维数组第i行的元素置0

为了访问到第i行的元素,让p指向数组a中第i行的第一个元素:

p=&a[i][0];

实际上,我们还可以将这句代码简写为

p=a[i];

对于任意一维数组a[]来说,其首元素地址为a。而二维数组可以看成是多个一维数组,行数就是一维数组的个数,列数就是数组中元素的个数。由此第i行的首元素地址就为a[i]。

如果要正经推导的话:对于任意数组a来说,表达式a[i]等价于(a + i)。因此&a[i][0]等同于&((a[i] + 0)),而后者等价于&a[i];又因为&和运算符可以抵消,也就等同于a[i]。

那么代码为:

int a[NUM_ROWS][NUM_COLS], *p, i;
for (p = a[i]; p < a[i] + NUM_COLS; p++)
*p = 0;

接下来我们再来思考一下怎么将数组a的第i列的元素置零呢?

我们可以利用数组指针(指向数组的指针)来实现这点。如声明一个数组指针:int (*p)[NUM_COLS]

我们知道,c语言指针每次自增1时,内存地址增加的量即为指针指向类型的所占内存单元数。在这里,p指向一个元素个数为NUM_COLS的int型数组,那么p++将会导致p指向地址增加NUM_COLS*(int型所占地址单元个数),这就实现了p从这一行指向了下一行。

代码如下

for(p = &a[0]; p < &a[NUM_ROWS]; p++){
(*p)[i] = 0;
}

最后,如果我们想遍历整个数组的话,也可以将整个二维数组看成一整个一维数组,利用指针进行遍历。

int *t;
for(t = a[0]; t <= &a[NUM_ROWS-1][NUM_COLS-1]; t++)
printf("%d ",*t);

c语言编程学习之二维数组的更多相关文章

  1. C语言中如何将二维数组作为函数的参数传递

    今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...

  2. 以杨辉三角为例,从内存角度简单分析C语言中的动态二维数组

    学C语言,一定绕不过指针这一大难关,而指针最让人头疼的就是各种指向关系,一阶的指针还比较容易掌握,但一旦阶数一高,就很容易理不清楚其中的指向关系,现在我将通过杨辉三角为例,我会用四种方法从内存的角度简 ...

  3. 程序员之--C语言细节13(二维数组和指针,&amp;*a[i][0]的理解,数组1[e]和e[1]非常可能你没见过)

    主要内容:二维数组和指针.&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_C ...

  4. 剑指Offer编程题1——二维数组中的查找

    剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...

  5. java学习之二维数组

    java当中的二维数组,存储一组比较特殊的对象.他存储一个数组,同时存储的数组当中又存储着元素. java二维数组的声明方式一: class Arr2Demo { public static void ...

  6. 基于visual Studio2013解决C语言竞赛题之0604二维数组置换

     题目

  7. Java学习之二维数组定义与内存分配详解

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

  8. 剑指Offer_编程题之二维数组中的查找

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

  9. Java 学习笔记 二维数组和对象数组

    定义二维数组 int[][] a = new int[4][5]; 可以不指定列数 int[][] a = new int[4][]; 获取行 int i = a.length(); 如果使用第一个例 ...

随机推荐

  1. Typora的一些快捷键

      语法格式 快捷键 标题 # + 空格 = 一级标题, ## + 空格 =二级标题, 以此类推 shift + 数字1 =一级标题 ,shift + 数字2 =二级标题 , 以此类推 有序列表 1 ...

  2. requirejs的用法

    requirejs的用法 2014年11月6日 17164次浏览 之前我的一片文章介绍过requirejs,具体地址是:http://www.haorooms.com/post/RequireJS_m ...

  3. x86汇编 条件跳转

    条件跳转表 汇编语言-条件跳转指令 直接转移指令 指令格式 机器码 测试标志 条件说明 符号  JO       OPR 70  OF=1  结果有溢出    JNO      OPR 71  OF= ...

  4. 全网最详细的新手入门Mysql命令和基础,小白必看!

    MySQL简介 什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是 ...

  5. 三分钟玩转微软AI量化投资开源库QLib

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 微软QLib简介 微软亚洲研究院发布了 AI 量化投资开源平台"微矿 Qlib".Q ...

  6. Java利用线程工厂监控线程池

    目录 ThreadFactory 监控线程池 扩展线程池 扩展线程池示例 优化线程池大小 线程池死锁 线程池异常信息捕获 ThreadFactory 线程池中的线程从哪里来呢?就是ThreadFoct ...

  7. [Fundamental of Power Electronics]-PART II-8. 变换器传递函数-8.1 Bode图回顾

    8.0 序 工程设计过程主要包括以下几个过程: 1.定义规格与其他设计目标 2.提出一个电路.这是一个创造性的过程,需要利用工程师的实际见识和经验. 3.对电路进行建模.变换器的功率级建模方法已经在第 ...

  8. BUAA_OO_第三单元

    一.JML初探 ​ JML(Java Modeling Language)作为一种形式化语言,可以约束Java代码中类和方法的状态和行为形成规格,通过将一系列具体代码实现抽象成明确的行为接口,可以形成 ...

  9. BUAA_2020_OO_UNIT2_REVIEW

    OO第二单元总结 1. 设计策略 总的来说,三次作业没有大的重构,都是使用了多线程进行电梯调度,输入线程和运行线程分离,主要的不同在于三次电梯调度器线程的数量有所不同,第一次为一个,第二次为n个,第三 ...

  10. git版本控制之三

    [删除文件]使用关键字 git rm '待删除的文件名或者文件夹名字'  这个默认会把本地和版本库里面的这个文件都删掉!!! 有一种情形就是我往版本库里面提交错了文件,我想从版本库里面移除,但是我本地 ...