二维数组

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. EfficientNet & EfficientDet 论文解读

    概述 总体而言,这两篇论文都在追求一件事,那就是它们名字中都有的 efficient.只是两篇文章的侧重点不一样,EfficientNet 主要时研究如何平衡模型的深度 (depth).宽度 (wid ...

  2. MarkDown-简单学习

    标题 注意:首部添加1-6个"#"号来设置标题大小: 字体 1:粗体 (注意:首尾同时添加2个"*"号来设置) 2:斜体 (注意:首尾同时添加1个"* ...

  3. PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) 凌宸1642

    PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) 凌宸1642 题目描述: At the beginning of ever ...

  4. 翻译:《实用的Python编程》08_00_Overview

    目录 | 上一节 (7 高级主题) | 下一节 (9 包) 8. 测试和调试 本节介绍与测试.日志和调试有关的基本主题. 8.1 测试 8.2 日志,错误处理和诊断 8.3 调试 目录 | 上一节 ( ...

  5. 源码级深挖AQS队列同步器

    我们知道,在java中提供了两类锁的实现,一种是在jvm层级上实现的synchrinized隐式锁,另一类是jdk在代码层级实现的,juc包下的Lock显示锁,而提到Lock就不得不提一下它的核心队列 ...

  6. springdata jpa之ddl-auto配置的属性

    在jpa中ddl-auto一共有四种: 分别为: ddl-auto:create ----每次运行该程序,没有表格会新建表格,表内有数据会清空:ddl-auto:create-drop ----每次程 ...

  7. Go-24-异常处理机制

    error 接口 type error interface(){ Error() string } 在Go语言中处理错误的方式通常是将返回的错误与nil进行比较.nil值表示没有发生错误,而非nil值 ...

  8. SpringBoot-容器启动的时候执行一些内容

    SpringBoot的ApplicationRunner.CommandLineRunner 场景: 在开发中可能会有这样的情景.需要在容器启动的时候执行一些内容.比如读取配置文件,数据库连接之类的. ...

  9. Searching the Web UVA - 1597

      The word "search engine" may not be strange to you. Generally speaking, a search engine ...

  10. 浅入Kubernetes(11):了解 Service 和 Endpoint

    目录 Srevice Service 的创建及现象 Service 定义 Endpoint slices 创建 Endpoint.Service Service 创建应用 创建 Endpoint 浅入 ...