当前位置: 首页 > article >正文

《C语言程序设计现代方法》note-5 数组

文章目录

    • 助记提要
    • 8章 数组
      • 8.1 一维数组
        • 数组下标
        • 数组初始化
        • sizeof
      • 8.2 多维数组
        • 初始化多维数组
        • 常量数组
      • 8.3 变长数组

助记提要

  1. 数组初始化格式;
  2. 指示器;
  3. 常量数组;
  4. 变长数组;

8章 数组

变量包括标量和聚合变量。标量可以保存单一数据项,聚合变量可以存储成组的数值。
C语言的聚合变量有数组和结构。

8.1 一维数组

数组是含有多个数据值的数据结构,且每个数据值的数据类型都相同。数据值也称为元素。
可以按照元素在数组中的位置把它们选出来。

一维数组中的元素依次排在一行中。

声明具有n个指定类型元素的数组arr:

类型 arr[n];

n可以是任何的(整数)常量表达式。

数组下标

为了存取指定的元素,可以在数组名后边加上一个方括号围绕的整数值。这个操作称为取下标或索引。

数组元素的下标始终从0开始,最大是n-1。n为数组长度。
注意 C语言不检查下标的范围,下标超出范围时,程序会执行预期外的行为。
下面的代码在i=10时,会把0存到a[9]后面。如果刚好后面的内存中是程序会用到的变量,这个变量值就会变为0。

int a[10], i;
for (i = 0; i <= 10; i++)
    a[i] = 0;

数组下标可以是任何整数表达式。但是为了便于理解,尽量不要在下标中使用有副作用的表达式。

数组和for循环搭配的惯用法:

// 清空
for (i = 0; i < n; i++)
    a[i] = 0;

// 读取数据存到数组
for (i = 0; i < n; i++)
    scanf("%d", &a[i]);

// 求和
for (i = 0; i < n; i++)
    sum += a[i]
数组初始化

数组可以在声明时给予初始值。

  • 初始化常用的格式是使用花括号包起来的常量表达式列表,逗号分隔;
  • 初始化列表比数组短时,数组的剩余元素赋值为0;
  • 初始化列表不能为空,也不能比数组大小长;
  • 给定初始化列表时,可以不写数组长度,编译器会利用列表长度确定数组大小。
// 初始化
int a[5] = {1, 2, 3, 4, 5};

// 剩余元素为0
int a[5] = {1, 2};

// 初始化全为0的数组
int a[5] = {0};

// 省略数组大小
int a[] = {1, 2, 3, 4, 5};

有时初始化时只需要对数组中的一部分元素赋值,其他元素默认为0即可。

// 直接赋值,数组越长越麻烦
int a[10] = {0, 0, 0, 7, 0, 0, 0, 0, 0, 4};

// 初始化0数组再分别赋值,赋值项多会很麻烦
int a[10] = {0};
a[3] = 7; 
a[9] = 4;

对于这个问题,C99提供了由方括号和常量表达式组成的指示器

int a[10] = {[3] = 7, [9] = 4};

指示器赋值的顺序不影响结果。
指示器的方括号内必须是整数表达式,且值不能超过数组下标上限。如果数组长度省略,指示器可以指定任何非负整数,编译器会按照其中的最大值推断数组的长度。

可以在逐个元素初始化的同时使用指示器:

int c[10] = {2, 1, [5] = 7, 6, 3, [9]=11};

指示器使用下标对元素多次初始化是合法操作,但是注意不要这么做。

// 重复初始化元素
int a[] = {4, 9, 1, 8, [0] = 5, 7};
// 上述声明的等价声明
int a[] = {5, 7, 1, 8};

编译器初始化数组时,会记录下一个待初始化的元素的位置。
指示器会强制指定一个元素做为编译器处理的下一元素,编译器从这个元素往后依次处理。

sizeof

sizeof可以确定数组的字节数。

利用数组大小除以数组元素的大小,可获取数组长度。这种方式写的表达式在数组长度需要改变时也不用重写:

for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	a[i] = 0;

有的编译器会对表达式i < sizeof(a) / sizeof(a[0])给出警告,因为sizeof但会的类型是size_t,不是int,把有符号整数和无符号整数相比较是危险的,虽然这里没有问题(都是正数)。
为了避免这个警告,可以把表达式的类型强制转为有符号整数或定义宏来表示它。

// 转为有符号整数
for (i = 0; i < (int) (sizeof(a) / sizeof(a[0])); i++)
    a[i] = 0;
#define SIZE ((int) (sizeof(a) / sizeof(a[0])); i++)
for (i = 0; i < SIZE; i++)
    a[i] = 0;

8.2 多维数组

数组可以有任意维度。每个维度的下标都以0开始。

// 创建二维数组
int m[5][9];

// 访问二维数组的元素
m[i][j];

注意 m[i][j]不可以写成m[i, j]。中括号内的逗号会被当做逗号运算符,m[i, j]等同于m[j]

多维数组在内存中仍然是按照行存储的。写程序时可以忽略这一细节,但是有时也会影响。

初始化多维数组

一维初始化格式嵌套可以初始化高维数组。

int m[3][4] = {{1, 1, 1, 1},
               {2, 2, 2, 2},
			   {3, 3, 3, 3}};
  • 如果嵌套的初始化列表没有填满多维数组,就把数组剩余的元素赋值为0;
  • 可以省略内层的花括号,编译器填满一行后开始填下一行。但是最好不要这样做,避免多填或少填元素的行影响整个数组。

C99的指示器也可以用于多维数组:

// 使用指示器初始化2×2的单位矩阵
int a[2][2] = {[0][0] = 1, [1][1] = 1};
常量数组

在声明时前面加上const,可以使数组称为常量数组。

const char hex_chars[] = {
    '0', '1', '2', '3', '4', '5', '6', '7', 
	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

程序不应该修改声明为const的数组,编译器会在发现数组被修改时提示错误。
这样的数组常常包含一些在程序执行中不会改变的参考信息。

8.3 变长数组

C99中允许数组变量的长度为非常量的表达式。
变长数组的长度在程序执行时计算,而不是在编译时计算。

由程序员指定数组长度的话,长度可能过长或过短。
变长数组的好处是不需要在构造数组时给定长度,而是在执行时精确计算长度。

变长数组的限制是没有静态存储期和没有初始化器。

goto语句不能绕过变长数组的声明。这样会导致程序对未分配空间的数组中的元素进行访问。


http://www.kler.cn/a/397870.html

相关文章:

  • Pytest从入门到精通
  • STM32寄存器结构体详解
  • GPIO相关的寄存器(重要)
  • 猎板PCB罗杰斯板材的应用案例
  • 丑数动态规划
  • 后端——接口文档(API)
  • 【开源免费】基于SpringBoot+Vue.JS卫生健康系统(JAVA毕业设计)
  • 【C++】OGRE:面向对象图形渲染库配置与示例
  • 2024山西省网络建设运维第十八届职业院校技能大赛解析答案(5. nginx 和 tomcat 服务)
  • 模型压缩相关技术概念澄清(量化/剪枝/知识蒸馏)
  • Pyhon基础数据结构(列表)【蓝桥杯】
  • 永磁同步电机负载估计--降阶龙贝格观测器
  • openai 论文Scaling Laws for Neural Language Models学习
  • 【项目日记】仿mudou的高并发服务器 --- 整体框架搭建 ,实现时间轮模块
  • 【Rust设计模式之新类型模式】
  • Android加载pdf
  • 鸿蒙HarmonyOS 地图不显示解决方案
  • ssm105基于JAVAEE技术校园车辆管理系统+jsp(论文+源码)_kaic
  • 力扣-Mysql-3278. 寻找数据科学家职位的候选人 II(中等)
  • 交易术语汇总(Technical Trading Dictionary)
  • FastAdmin 部署二开项目遇到 “No input file specified“ 的解决方案
  • 整数唯一分解定理
  • (干货)Jenkins使用kubernetes插件连接k8s的认证方式
  • MySQL技巧之跨服务器数据查询:高级篇-先调用A数据库的MySql存储过程再复制到B数据库的表中
  • 连续九届EI稳定|江苏科技大学主办
  • pytest在conftest.py中实现用例执行失败进行截图并附到allure测试报告