初始C语言 - 数组(一维数组、二维数组、数组越界、数组传参)
目录
一、一维数组的创建和初始化
1、数组的创建
2、 数组的初始化
3.一维数组的使用
数组通过下标来访问
总结:
1. 数组是使用下标来访问的,下标是从0开始。
2. 数组的大小可以通过计算得到。
4、一维数组在内存中的存储
二、 二维数组的创建和初始化
1.二维数组的创建
2.二维数组的初始化
二维数组的初始化:行可以省略,列不能省略
3.二维数组的使用
二维数组的使用也是通过下标的方式。
4、二维数组在内存中的存储
三、 数组越界
数组的下标是有范围限制的。
四、数组作为函数参数
错误设计(冒泡排序):
错误原因:误以为传递的参数时整个数组,其实时数组首元素地址
引出了一个问题:
调试之后可以看到 bubble_sort 函数内部的 sz ,是1。
难道数组作为函数参数的时候,不是把整个数组的传递过去?
数组传参规则:
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数
组。
2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
正确设计 - 冒泡排序
一、一维数组的创建和初始化
1、数组的创建
数组是一组相同类型元素的集合。type_t arr_name [const_n];//type_t 是指数组的元素类型//const_n 是一个常量表达式,用来指定数组的大小
数组什么时候创建?注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。所以:代码2是错误的例子
//代码1
int arr1[10];
//代码2 - 错误示范
int count = 10;
int arr2[count];//数组时候可以正常创建?
//代码3
char arr3[10];
float arr4[1];
double arr5[20];
试了一下,此环境下不支持C99标准,可以从这个n下面的红波浪线看出来,报错了,这里的数组[]
里面只能是常量!!!!
2、 数组的初始化
数组的初始化是指:在创建数组的同时给数组的内容一些合理初始值(初始化)
初始化有完全初始化和不完全初始化
完全初始化:数组指定了明确的元素个数,且每个元素空间里都有元素
不完全初始化:数组指定了元素个数,但元素空间有剩余,没有占满整个数组空间,默认补0
int main()
{//完全初始化int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//不完全初始化,剩余的默认初始化为0int arr2[10] = { 1,2,3,4,5 };//1 2 3 4 5 0 0 0 0 0 int arr3[10] = { 0 };// 0 0 0 0 0 0 0 0 0 0 //字符数组:可以放单个字符char ch1[5] = { 'a','b',99 };//a b c 0 0 0 //可以放字符串char ch2[10] = "abcdef";//数组初始化,可以不知道数组元素大小,但必须有数组内容,数组的大小会根据数组内容来确定char ch3[] = "abc";char ch4[] = { 'a','b','c' };printf("%s\n", ch3);//abc //遇到\0就结束了printf("%s\n", ch4);//abc烫烫烫烫蘟bc //打印完abc之后随机打印,直到遇到\0return 0;
}
3.一维数组的使用
数组通过下标来访问
对于数组使用操作符: [] ,下标引用操作符。它其实就数组访问的操作符
总结:
1. 数组是使用下标来访问的,下标是从0开始。
2. 数组的大小可以通过计算得到。
int arr[10];int sz = sizeof(arr)/sizeof(arr[0]);
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };// 0 1 2 3 4 5 6 7 8 9printf("%d\n", arr[9]);//打印下标为9的元素10//打印数组int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < 10; i++){printf("%d ", arr[i]);}int a = 10;printf("%d\n", sizeof(arr));//40printf("%d\n", sizeof(int[10]));printf("%d\n", sizeof(a));printf("%d\n", sizeof(int));return 0;
}
4、一维数组在内存中的存储
仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。由此可以得出结论:数组在内存中是连续存放的。
int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < 10; i++){printf("&arr[%d]=%p\n", i,&arr[i]);}return 0;
}
可以看出来:地址是用16进制表示的。0~9和a~f(0~15)
整型数组,首元素地址C0结尾,因为整型占4字节,+4之后就是下一个元素的首元素地址C4,依次类推第三个元素首元素地址为C8..
二、 二维数组的创建和初始化
1.二维数组的创建
//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4]; 2.二维数组的初始化
二维数组的初始化:行可以省略,列不能省略
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};//二维数组如果有初始化,行可以省略,列不能省略
3.二维数组的使用
二维数组的使用也是通过下标的方式。
int main()
{//3行4列//int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//int arr1[3][4] = { {1,2},{3,4},{5,6} };//char arr2[5][6];//5行6列//二维数组的初始化:行可以省略,列不能省略//int arr1[][4] = { {1,2},{3,4},{5,6} };int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//printf("%d\n", arr1[1][2]);//7//打印二维数组int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("%-2d ", arr1[i][j]);}printf("\n");}return 0;
}

4、二维数组在内存中的存储
二维数组看似多行多列,实际上是连续存储的,本质上还是个一维数组
如果把二维数组的每一行看作一个一维数组,那么每一行的一维数组
也有数组名,arr[0]就是第一行的数组名,arr[1]就是第二行的数组名,以此类推

int main()
{int arr[3][4] = { 0 };int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 4; j++){printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);}}return 0;
}

三、 数组越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。一维数组、二维数组都可能存在越界。C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的, 所以程序员写代码时,最好自己做越界的检查
int main()
{int arr[10] = { 0 };int i = 0;for (i = 0; i <= 10; i++)//越界了{printf("%d ", arr[i]);//能运行代码,但在这里arr[i]能看到警告}return 0;
}
可以发现:访问数组内部下标0~9的元素时,都正常打印 0,但是越界打印下标为10的元素,是一个随机值,同时在没有运行的时候,编译器也提示了,在arr[i]下面提示绿色波浪线;
四、数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(这里要讲算法 思想)写函数 将一个整形数组排序。在不了解传参真正传递的是什么时候,很容易出现的问题:
错误设计(冒泡排序):
错误原因:误以为传递的参数时整个数组,其实时数组首元素地址
导致了在函数中,计算数组大小时 ,int sz = sizeof(arr)/sizeof(arr[0]);//传参出现问题,sz=1
其实是首元素大小/首元素大小=1。
正确做法:在主函数计算完,再一起传参给函数
//方法1:
#include <stdio.h>
void bubble_sort(int arr[])
{int sz = sizeof(arr)/sizeof(arr[0]);//传参出现问题,sz=1 这样对吗?int i = 0;for(i=0; i<sz-1; i++){int j = 0;for(j=0; j<sz-i-1; j++){if(arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;}}}
}
int main()
{int arr[] = {3,1,7,5,8,9,0,2,4,6};bubble_sort(arr);//是否可以正常排序?for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++){printf("%d ", arr[i]);}return 0;
}
发现并没有按照我们预期的排序
引出了一个问题:
调试之后可以看到 bubble_sort 函数内部的 sz ,是1。
难道数组作为函数参数的时候,不是把整个数组的传递过去?
数组传参规则:
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数
组。
2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址。
1、数组传参传递的是:首元素地址
可以发现:当我们打印数组的地址时,和打印数组第一个元素时,是同一个地址,也就说明了arr的地址就是首元素地址,同时我们对arr地址解引用,得到了第一个元素的值1,更能确信的确是这样

2、数组有时候也代表整个数组

正确设计 - 冒泡排序
正确使用数组传参,完成冒泡排序:先在主函数求出整个数组的大小,传参时再传递数组首元素地址和数组大小
void bubble_sort(int arr[], int sz)//参数接收:数组arr首元素地址,数组元素个数
{//代码同上面函数
}int main()
{int arr[] = {3,1,7,5,8,9,0,2,4,6};int sz = sizeof(arr)/sizeof(arr[0]);bubble_sort(arr, sz);//是否可以正常排序?for(i=0; i<sz; i++){printf("%d ", arr[i]);}return 0;
} 现在运行,正常排序了

相关文章:
初始C语言 - 数组(一维数组、二维数组、数组越界、数组传参)
目录 一、一维数组的创建和初始化 1、数组的创建 2、 数组的初始化 3.一维数组的使用 数组通过下标来访问 总结: 1. 数组是使用下标来访问的,下标是从0开始。 2. 数组的大小可以通过计算得到。 4、一维数组在内存中的存储 二、 二维数组的创建和初始化 1.二…...
人工智能原理复习 | 可分解产生式系统的搜索策略
文章目录 一、前言二、基础知识三、AO* 算法四、博弈树搜索五、总结CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 主要内容: 与 / {/} /或图搜索、AO* 算法、极大极小过程、...
线段树(维护区间信息)
一,定义: 可以在logN时间内实现区间修改,单点修改,区间查询等操作的工具 二,思路(修改无乘法时): 1,建树 通过把区间不断二分建立一颗二叉树 我们以维护一个数组a{1…...
C语言 基于Ncurse库的贪吃蛇游戏项目
为了敲键盘及时响应,需要用到ncurse 测试代码: ncurse1.c /* ncurse1.c */ #include <curses.h> //ncurse的头文件。int main() {char c;int i 0;//ncurse界面的初始化函数。initscr(); for(i0;i<2;i){c getch();printw("\n");//…...
【Java基础】Java语言特性
认识Java java语言的执行过程 编写纯文本文件 .java 经过javac编译器(java complier)编译 .class .class是二进制的字节码 在源文件中定义几个类,就会生成几个 由JVM运行 .class JVM把字节码编译成可以在处理器上运行的高性能的本地代码(native code),…...
python进阶--Numyp库(一)
一、Numpy库介绍 NumPy(Numerical Python)是Python的⼀种开源的数值计算扩展。提供多维数组对象,各种派⽣对象(如掩码数组和矩阵),这种⼯具可⽤来存储和处理⼤型矩阵,⽐Python⾃身的嵌套列表&am…...
CV学习笔记-Inception
CV学习笔记-Inception 目录 文章目录CV学习笔记-Inception目录1. 常见的卷积神经网络2. Inception(1) Inception提出背景(2) Inception module 核心思想3. Inception的历史版本(1) InceptionV1-GoogleNet(2) InceptionV2(3) InceptionV3(4) Inception V44. Inception模型的特点…...
注意力机制笔记——结合沐神和B站老弓up主
B站【大白话浅谈【注意力机制】】 聚类 是针对 样本, 注意力机制是针对样本相关性,来进行计算的 自注意力机制 指的是 query ,key,value都是同一个部分。 可以学到 类似的 短语 ,和 语义特征。如its 指代的对象。 评论区大佬 根据这篇论文《Effective Approaches to…...
建议收藏,轻松搞懂区块链
未来已来,只是不均衡地分布在当下 大家好,我是菜农,欢迎来到我的频道。 本文共 5844字,预计阅读 30 分钟 区块链是近些年来最热门的前沿技术,被认为是未来十几年对金融、物联网、医疗等诸多领域产生最大影响的"…...
php设计一个新春祝福墙
记得十几年前的时候,每到春节,各大网站都会建一个祝福墙,上面挂满网友的新年寄语。这些年随着移动互联网的高速发展,web的新春祝福墙越来越少了。今天,咱们就来考考古,用快速原型法进行设计。原型设计采用M…...
KubeSphere 社区双周报 | OpenFunction 集成 WasmEdge | 2023.02.03-02.16
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为:2023.02.03-2023.…...
数字IC/FPGA 秋招知识点不全面整理
1. 引言 这篇文章的由来 秋招的时候,刚开始复习一些知识点的时候没有什么思路,只是盲目的看相关的书籍和资料,结果是留在脑子中的知识很有限,而且不够系统,在我需要它的时候,并不能很快的回忆起来。 于是就想着把一些典型的知识整理成一个文档,在进行刷题的时候可以比…...
你知道java8是如何排序Map嘛?
在Java中,有多种方法可以对Map进行排序,但是我们将重点介绍Java 8 Stream,这是实现目标的一种非常优雅的方法。 学习一下HashMap的merge()函数 在学习Map排序之前,有必要讲一下HashMap的merge()函数,该函数应用场景就…...
【李忍考研传】一、李忍
“老师,我来回答!” “非常好,我记得你是叫……呃……是李念同学吗?” “不,老师,我叫李忍。” “好,你来回答一下这个问题。” “这题用海明码校验的知识,能检错一位纠错一位&a…...
测牛学堂:软件测试python深入之类和对象的属性和方法总结
类对象和实例对象 类对象就是我们定义的类。 在代码执行的时候,解释器会自动创建类对象。 类对象的作用: 1 使用类对象创建实例对象 2 存储类的一些特性,就是类里面定义的属性 创建对象的过程也称为实例化的对象。所以,类创建的对…...
css实例--新闻页面
实现效果 实现代码 html代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" co…...
SpringCloudGateway 动态转发后端服务
API网关的核心功能是统一流量入口,实现路由转发,SpringCloudGateway是API网关开发的技术之一,此外比较流行的还有Kong和ApiSix,这2个都是基于OpenResty技术栈。 简单的路由转发可以通过SpringCloudGateway的配置文件实现…...
使用canvas写一个flappy bird小游戏
简介 canvas 是HTML5 提供的一种新标签,它可以支持 JavaScript 在上面绘画,控制每一个像素,它经常被用来制作小游戏,接下来我将用它来模仿制作一款叫flappy bird的小游戏。flappy bird(中文名:笨鸟先飞&am…...
KVM-2、虚拟化基础
1. 虚拟化概念 什么是虚拟化 **虚拟化是使用所谓虚拟机管理程序从一台物理机上创建若干个虚拟机的过程。**虚拟机的行为和运转方式与物理机一样,但它们会使用物理机的计算资源,如 CPU 、内存和存储。虚拟机管理程序会根据需要将这些计算资源分配给每个虚拟机。 虚拟化有哪…...
设计模式之观察者模式与访问者模式详解和应用
目录1.访问者模式详解1.1 访问者模式的定义1.1.1 访问者模式在生活中的体现1.1.2 访问者模式的适用场景1.2 访问者模式的通用实现1.3 访问者模式的使用案例之KPI考核1.3.1 类图设计1.3.2 代码实现1.4 访问者模式扩展---分派1.4.1 java中静态分派示例代码1.4.2 java中动态分派1.…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...



