初始C语言 - 数组(一维数组、二维数组、数组越界、数组传参)

news2024/9/24 13:26:14

目录

 

一、一维数组的创建和初始化

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 };
	//不完全初始化,剩余的默认初始化为0
	int 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之后随机打印,直到遇到\0
	return 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 9
	printf("%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));//40
	printf("%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;
}

现在运行,正常排序了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法导论【分治思想】—大数乘法、矩阵相乘、残缺棋盘

这里写自定义目录标题分治法概述特点大数相乘问题分治算法矩阵相乘分治算法残缺棋盘分治算法分治法概述 在分而治之的方法中&#xff0c;一个问题被划分为较小的问题&#xff0c;然后较小的问题被独立地解决&#xff0c;最后较小问题的解决方案被组合成一个大问题的解决。 通常…

【软件测试】自动化测试工程师必会的单元测试编写(总结),你真的了解吗......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 单元测试编写的目的…

supervisor-男程序员的福音

supervisor是什么 supervisor是用python语言编写的&#xff0c;只能用于类Unix系统上的进程管理工具。 supervisor有什么用 举一个常见的场景&#xff0c;比如你的项目已经到了测试联调阶段&#xff0c;QA需要你把程序启动起来&#xff0c;然后进行测试&#xff0c;那么启动…

用Java实现多线程打印奇偶数

用Java实现多线程打印奇偶数1. wait()和 notify() 方法的作用&#xff1a;2. Java实现&#xff08;1&#xff09;Thread1.class 奇数线程&#xff08;2&#xff09;Thread2.class 偶数线程&#xff08;3&#xff09;共享资源类&#xff08;4&#xff09;测试1. wait()和 notify…

一篇文章带你玩转 Kubernetes:组件、核心概念和Nginx实战演示

目录一、简介1.1 容器部署时代1.2 Kubernetes有哪些优点二、Kubernetes 组件介绍三、Kubernetes 核心概念3.1 Namespace3.2 Pod3.3 Deployment3.4 Service3.5 Ingress四、Kubernetes 核心概念实战4.1 部署yaml文件4.2 通过Pod IP访问Nginx4.3 通过Service IP访问Nginx4.4 修改i…

[数据结构]:顺序表(C语言实现)

目录 前言 顺序表实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-SeqListCommon.cpp 04-SeqListPositionOperation.cpp 05-SeqListValueOperation.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为…

node+vue微信小程序的社区后勤报修系统

社区后勤报修系统小程序进行总体设计和详细设计。总体设计主要包括小程序功能设计、小程序总体结构设计、小程序数据结构设计和小程序安全设计等&#xff1a;详细设计主要包括社区后勤报修系统小程序数据库访问的实现,主要功能模块的具体实现,模块实现关键代码等。最后对社区后…

目标检测论文阅读:DETR算法笔记

标题&#xff1a;End-to-End Object Detection with Transformers 会议&#xff1a;ECCV2020 论文地址&#xff1a;https://link.springer.com/10.1007/978-3-030-58452-8_13 官方代码&#xff1a;https://github.com/facebookresearch/detr 作者单位&#xff1a;巴黎第九大学、…

【Linux】进程替换

文章目录进程程序替换替换原理替换函数函数返回值函数命名理解在makefile文件中一次生成两个可执行文件总结:程序替换时运行其它语言程序进程程序替换 程序要运行要先加载到内存当中 , 如何做到? 加载器加载进来,然后程序替换 为什么? ->冯诺依曼 因为CPU读取数据的时候只…

【原创】java+swing+sqlserver药品管理系统设计与实现

之前数据库都是用的mysql&#xff0c;今天我们使用sqlserver在配合swing来开发一个药品管理系统。方便医院工作人员进行药品的管理&#xff0c;基础功能基本都是一些增删改查操作。 功能分析&#xff1a; 药品管理系统主要提供给管理员和员工使用&#xff0c;功能如下&#x…

[python]win10安装gym

anconda3里面安装&#xff1a; pip install gym[atari,accept-rom-license]0.26.1 AutoRom 测试结果&#xff1a; import gym envgym.make(Assault-v4,render_modehuman) env.reset() for _ in range(100000): actionenv.action_space.sample() env.step(action) env.c…

数据结构——算法的时间复杂度

&#x1f307;个人主页&#xff1a;_麦麦_ &#x1f4da;今日名言&#xff1a;生命中曾经有过的所有灿烂&#xff0c;都终究需要用寂寞来偿还。——《百年孤独》 目录 一、前言 二、正文 1.算法效率 1.1如何衡量一个算法的好坏 1.2算法的复杂度 2. 时间复杂度 2.1时间复杂度的…

元胞自动机

文章目录前言文献阅读摘要主要贡献方法框架实验结论元胞自动机元胞自动机是什么&#xff1f;构成及规则案例及代码实现总结前言 This week,the paper proposes a Multi-directional Temporal Convolutional Artificial Neural Network (MTCAN) model to impute and forecast P…

部署dapr的辛酸历程

前言dapr大概的了解&#xff0c;个人理解他就是一个分布式服务的管理&#xff0c;把微服务常用的组件(缓存&#xff0c;消息中间件、分布式锁、安全id4等)和监控以及服务注册、发现等等一系列功能以一个很抽象的方式管理起来。可能我们部署微服务用consul、ocelot、polly套件、…

DDD单根 聚合根 实体 值对象

前言2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software &#xff08;领域驱动设计&#xff09;&#xff0c;简称Evans DDD。快二十年的时间&#xff0c;领域驱动设计在不断地发展&#xff0c;后微服务时代强调的东西&#xff0c;在国…

Nginx网站服务及优化

Nginx网站服务及优化一、简介1、Nginx概述2、Nginx和Apache的优缺点比较3、Nginx和Apache最核心的区别二、Linux中的I/O三、Nginx编译安装详细1、关闭防火墙、安装依赖关系2、新建用户nginx便于管理3、将压缩包传入到/opt目录下&#xff0c;编译安装4、做软连接并启动nginx5、创…

软件测试简历个人技能和项目经验怎么写?(附项目资料)

目录 前言 个人技能 项目实战经验 项目名称&#xff1a;苏州银行项目&#xff08;webapp&#xff09; 项目描述&#xff1a; 项目名称&#xff1a;中国平安项目&#xff08;webapp&#xff09; 项目描述&#xff1a; 项目名称&#xff1a;苏宁易购项目&#xff08;webapp&a…

软件体系结构(期末复习)

文章目录软件体系结构软件体系结构概论软件体系结构建模软件体系结构风格统一建模语言基于体系结构的软件开发软件体系结构 软件体系结构概论 软件危机是指计算机软件的开发和维护过程中遇到的一系列严重问题。 软件危机的表现: 软件危机的原因: 软件工程的基本要素&#xf…

轻松上手nacos使用

三步上手nacos使用1.为什么使用nacos?2.如何使用nacos1.为什么使用nacos? 1.服务发现中心。 微服务将自身注册至 Nacos&#xff0c;网关从 Nacos 获取微服务列表。 2.配置中心。 微服务众多&#xff0c;它们的配置信息也非常复杂&#xff0c;为了提高系统的可维护性&#xf…