C语言学习笔记——5(数组)

张开发
2026/5/3 23:17:50 15 分钟阅读
C语言学习笔记——5(数组)
数组数组的定义数组是构造数据类型之一用于存储相同类型数据的集合。数组的特点组成数组的各个变量称为数组的元素数组中各元素的数据类型要求相同元素在内存中是连续依次排列的属于构造数据类型由基本类型组合而成一维数组一维数组的定义数据类型 数组名[元素个数];int arr[5]; // 定义一个包含5个整数的数组 float scores[10]; // 定义一个包含10个浮点数的数组一维数组的初始化方式一元素全部初始化int a[5] {1, 2, 3, 4, 5}; // 完全初始化方式二元素部分初始化int b[5] {1, 2, 3}; // 前3个元素初始化后2个自动为0方式三元素全部不初始化int c[5]; // 元素值为随机数取决于内存原有内容方式四省略元素数量初始化int d[] {1, 2, 3, 4, 5}; // 编译器自动推断数组大小为5一维数组的引用int arr[3] {10, 20, 30}; arr[0] 100; // 修改第一个元素 int value arr[2]; // 获取第三个元素值为30一维数组的内存分配数组元素是连续存储的数组占用内存空间 数组元素个数 × sizeof(元素数据类型)#include stdio.h int main() { int a[3]{0,1,2}; printf(sizeof(int):%ld\n,sizeof(int)); for(int i 0;i3;i) { printf(a[i]:%d , a[i]:%p\n,a[i],a[i]); } return 0; }运行结果注意地址是连续递增的每个int类型占用4字节。字符串数组需要注意的两点char str[] Hello; // 实际存储为 H,e,l,l,o,\0 printf(%s\n, str); // 输出 Hello原理%s会从数组的首地址开始逐个字符输出直到遇到\0才停止。关键如果字符数组没有\0例如char str[5] Hello;且没留结束符位置printf(%s)会继续往后读取内存直到偶然碰到一个\0才停下结果可能是乱码甚至程序崩溃。char c[] {H,E,L,L,O}; // 没有自动添加 \0那么这个数组只包含五个字符没有结束符\0%s会从c的首地址开始一直输出直到遇到内存中的\0才停止。由于数组末尾没有\0printf会越过数组边界继续读取内存直到偶然碰上一个值为0的字节为止。数组名的含义数组名代表整个数组数组名代表数组的首地址printf(起始地址a:%p a[0]:%p\n,a,a[0]); 起始地址a:0x7fffd75fe1fc a[0]:0x7fffd75fe1fc数组占用内存空间sizeof(数组名)printf(数组空间sizeof(a):%ld 3*sizeof(int)%ld\n,sizeof(a),3*sizeof(int)); 数组空间sizeof(a):12 3*sizeof(int)12数组元素个数sizeof(数组名)/sizeof(元素数据类型)sizeof(a)/sizeof(int)数组的越界什么是数组越界访问数组时使用了超出数组定义范围的下标。示例int arr[5] {1, 2, 3, 4, 5}; arr[5] 6; // 越界访问数组下标有效范围是0-4越界的危害可能修改其他变量的值内存覆盖可能导致程序崩溃产生不可预知的行为数组中找出最大值#include stdio.h int main() { int a[3]{5,4,9}; int max a[0]; for(int i 2;i3;i) { if(maxa[i]) { max a[i]; } } printf(max:%d\n,max); return 0; }运行结果max:9二维数组二维数组的定义数据类型 数组名[行数][列数];int matrix[3][4]; // 3行4列的整型二维数组 float scores[5][3]; // 5行3列的浮点型二维数组 char board[8][8]; // 8行8列的字符型二维数组如棋盘二维数组的存储存储方式二维数组在内存中是按行连续存储的先存储第0行的所有元素然后是第1行依此类推验证存储连续性的代码#include stdio.h int main() { int arr[2][3] {{1, 2, 3}, {4, 5, 6}}; printf(二维数组内存地址\n); for(int i 0; i 2; i) { for(int j 0; j 3; j) { printf(arr[%d][%d] %d, 地址%p\n, i, j, arr[i][j], arr[i][j]); } } return 0; }运行结果示例二维数组内存地址 arr[0][0] 1, 地址0x7ffd5e3a4e00 arr[0][1] 2, 地址0x7ffd5e3a4e04 arr[0][2] 3, 地址0x7ffd5e3a4e08 arr[1][0] 4, 地址0x7ffd5e3a4e0c arr[1][1] 5, 地址0x7ffd5e3a4e10 arr[1][2] 6, 地址0x7ffd5e3a4e14内存大小计算总大小 行数 × 列数 × sizeof(元素类型)二维数组的引用数组名[行下标][列下标]二维数组的初始化完全初始化// 方式1按行分组 int arr1[2][3] { {1, 2, 3}, {4, 5, 6} }; // 方式2连续赋值按内存顺序 int arr2[2][3] {1, 2, 3, 4, 5, 6};部分初始化// 未指定的元素自动初始化为0 int arr3[3][4] { {1}, // 第一行1,0,0,0 {0, 2}, // 第二行0,2,0,0 {0, 0, 3} // 第三行0,0,3,0 };省略行数初始化行数可省列数不可省// 编译器自动计算行数 int arr4[][3] {1, 2, 3, 4, 5, 6}; // 2行3列 int arr5[][3] {{1}, {2, 3}, {4, 5, 6}}; // 3行3列 int arr6[][4] {{1, 2}, {3, 4}, {5, 6}}; // 3行4列内存特性特性说明存储方式按行连续存储地址计算arr[i][j] 基地址 (i × 列数 j) × sizeof(元素类型)总大小行数 × 列数 × sizeof(元素类型)打印二维数组#include stdio.h int main() { int a[][3]{{0,1,2},{3,4}}; int c,l; c sizeof(a)/sizeof(a[0]); l sizeof(a[0])/sizeof(int); printf(sizeof(a):%ld\n,sizeof(a)); printf(sizeof(a[0]):%ld\n,sizeof(a[0])); printf(l:%d,c:%d\n,l,c); for(int i0;ic;i) { for(int m0;ml;m) { printf(%d ,a[i][m]); } printf(\n); } return 0; } ~sizeof(a):24 sizeof(a[0]):12 l:3,c:2 0 1 2 3 4 0二维数组下三角打印二维数组输出所有值并求和输出二维数组最大值并写出最大值所在的位置二维数组矩阵的转置杨辉三角形修改之后数组越界风险当 j0时a[i][j-1]会越界访问字符数组元素的数据类型是字符类型char str1[10]; // 未初始化 char str2[10] {H, e, l, l, o}; // 逐个字符初始化 char str3[] {H, e, l, l, o}; // 自动计算大小5 char str4[] Hello; // 字符串初始化包含\0 char str5[10] Hello; // 部分初始化剩余为\0字符串是以 \0空字符ASCII码为0结尾的字符数组// 这不是字符串缺少\0 char not_str[5] {H, e, l, l, o}; // 这是字符串包含\0 char is_str[6] {H, e, l, l, o, \0}; char auto_str[] Hello; // 编译器自动添加\0大小为6字符串的用法%s#include stdio.h int main() { char str[100] Hello World; printf(%s\n, str); // 输出Hello World // 输入字符串遇空格/tab/换行终止 printf(Enter a string: ); scanf(%s, str); // 输入Hi there只读取Hi printf(%s\n, str); // 输出Hi //这个时候将%s替换为%[^\n]则可实现输出Hi there return 0; }字符数组 ≠ 字符串字符串必须有\0结尾%s格式符输出时遇到\0停止输入时遇空白符停止必须是字符串才能用%s,字符数组不能乱用。二维字符数组二维字符数组实际上是一个字符串数组每个元素是一个字符串字符数组#include stdio.h int main() { char a[][5]{zrz,zjy,zzz}; for (int i0;isizeof(a)/sizeof(a[0]);i){ printf(%s\n,a[i]); } return 0; }

更多文章