C语言辨析——声明int a[3][6], a[0][9]越界吗?

本文来源:声明int a[3][6], a[0][9]越界吗?

1. 问题

看下面的程序:


#include <stdio.h> 
int main(void) 
{
  int a[3][6];
  for(int i=0; i<3; i++) {
    for(int j=0; j<6; j++){
      a[i][j] =i * 6 + j;
    }
  }
  printf("%d\n",a[0][9]);
  return 0;
}

第10行中的数组元素a[0][9]中的下标9越界吗?

这是一个关于二维数组的问题,下面先了解一下二维数组的相关知识。

2. 二维及多维数组定义和存储方式

二维数组通常用于表示由固定多个同类型的、具有行列结构的数据所构成的复合数据。

二维数组定义的一般形式是:

类型说明符 数组名[元素长度1][元素长度2];

其中类型说明符、数组名的含义和一维数组完全相同。元素长度1表示数组第一维(高维)的长度,元素长度2 表示第二维的长度。二维数组经常用来表示行列式,因此第一维也称为行,第二维也称为列。例如:

int mat[3][4];

定义了一个三行四列的二维数组,数组名为mat,该数组共有3×4=12个int类型元素,每个元素的名称、前后顺序如图1所示。

图片

图1 二维数组mat

二维数组的两个下标在横向和纵向两个方向上变化,而不像一维数组只是一个方向。但是,计算机中存储器是一维编址的,或者说存储器单元是按一维线性排列的,只有一个方向。那么如何在一维结构的存储器中存放二维数组呢,一般有两种方式存储二维数组:一种是按行优先存放,即存放完二维数组第一行之后再存放入第二行;另一种是按列优先存放,即存放完二维数组第一列之后再存放第二列。C实现都是按行优先存放。

因此图1所示二维数组mat,各元素在存储器中存放的先后次序为:

mat[0][0],mat[0][1],mat[0][2],mat[0][3],mat[1][0],mat[1][1],mat[1][2],mat[1][3],mat[2][0],mat[2][1],mat[2][2],mat[2][3]

和一维数组一样,二维数组定义后,系统会在内存中为二维数组分配一块连续区域,从内存的低地址开始依次存放二维数组的各元素数据。因此mat[3][4]定义以后,12个整型元素存放在一块连续的内存中。这一原则对任何类型的数组都成立。

3. C标准的规定

C标准规定,多维数组按行优先存放。在附录J.2 未定义行为一节中列出了下标越界,这说明,下标越界属于未定义行为。

An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6).

给定声明int a[4][5],显然左值表达式a[1][7]给定的下标是可以访问的,但其数组下标越界了(6.5.6)。

4. 结论

声明int a[3][6], 则a[0][9]的下标越界。

对于数组越界来说,它属于未定义行为。任何未定义行为都是潜在的bug。但C编译器对数组越界不进行判断,对于a[0][9]仍可以正常访问,我们可以认为这是一个假越界。

对于声明int a[3][6]来说,a[i][j]等价于 *(a+(i*6+j)*sizeof(int))。

如果i*6+j<3*6,且0<=i<3, j>=6,我们定义这种情况为假越界,程序可以正常访问,这是一个假bug。

如果i*6+j>=3*6,且 i>=0, j>=0,我们定义这种情况为真越界。可以判断这是一个真的bug。

相关推荐

  1. C语言】数组越界

    2024-02-13 17:42:02       37 阅读
  2. C语言面试指针辨析

    2024-02-13 17:42:02       46 阅读
  3. C语言 数组声明

    2024-02-13 17:42:02       37 阅读
  4. C语言—用题目辨析gets()与scanf()

    2024-02-13 17:42:02       38 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-13 17:42:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-13 17:42:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-13 17:42:02       87 阅读
  4. Python语言-面向对象

    2024-02-13 17:42:02       96 阅读

热门阅读

  1. 鸿蒙harmony--TypeScript类详解

    2024-02-13 17:42:02       46 阅读
  2. Redis的持久化方式

    2024-02-13 17:42:02       49 阅读
  3. 接口测试:项目测试

    2024-02-13 17:42:02       48 阅读
  4. 异步复位同步释放原则

    2024-02-13 17:42:02       45 阅读
  5. Day31 贪心算法part01

    2024-02-13 17:42:02       58 阅读
  6. 1277. 统计全为 1 的正方形子矩阵

    2024-02-13 17:42:02       59 阅读
  7. Ubuntu Desktop 开机数字小键盘

    2024-02-13 17:42:02       61 阅读
  8. 【力扣每日一题】力扣144二叉树的前序遍历

    2024-02-13 17:42:02       59 阅读
  9. 网站一天要是能有一万自然ip流量能有多少钱

    2024-02-13 17:42:02       65 阅读
  10. c语言—指针排序

    2024-02-13 17:42:02       45 阅读