C语言数组【详解】

news2024/10/3 0:22:04

在这里插入图片描述

数组

  • 1. 一维数组的创建和初始化
    • 1.1 数组的创建
    • 1.2 数组的初始化
    • 1.3 一维数组的使用
    • 1.4 一维数组在内存中的存储
  • 2. 二维数组的创建和初始化
    • 2.1 二维数组的创建
    • 2.2 二维数组的初始化
    • 2.3 二维数组的使用
    • 2.4 二维数组在内存中的存储
  • 3. 数组越界
  • 4. 数组作为函数参数
    • 4.1 冒泡排序函数的错误设计
    • 4.2 数组名是什么?
    • 4.3 冒泡排序函数的正确设计

1. 一维数组的创建和初始化

1.1 数组的创建

数组是一组相同类型元素的集合。
数组的创建方式:

type_t arr_name [const_n];
type_t 是指数组的元素类型
const_n 是一个常量表达式,用来指定数组的大小

数组创建的实例:

char arr3[10];
float arr4[1];
double arr5[20];

:数组创建,在C99标准之前, [ ] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数
组的概念,数组的大小可以使用变量指定,但是数组不能初始化。

1.2 数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
看代码:

int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {‘a’,98, ‘c’};
char arr5[] = {‘a’,‘b’,‘c’};
char arr6[] = “abcdef”;

数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
但是对于下面的代码要区分,内存中如何分配

char arr1[ ] = “abc”;//包含/0
char arr2[3] = {‘a’,‘b’,‘c’};//不包含/0

1.3 一维数组的使用

对于数组的使用我们之前介绍了一个操作符: [ ] ,下标引用操作符。它其实就数组访问的操作符。
我们来看代码:

#include <stdio.h>
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", arr[9]);
	return 0;
}

结果为10
继续看接下来的代码(计算数组的元素个数):

#include <stdio.h>
int main()
{
    int arr[10] = {0};//数组的不完全初始化
    //计算数组的元素个数
    int sz = sizeof(arr)/sizeof(arr[0]);
    //对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
    int i = 0;//做下标
    for(i=0; i<10; i++)//这里写10
        {
             arr[i] = i;
        }
    //输出数组的内容
       for(i=0; i<10; ++i)
          {
                printf("%d ", arr[i]);
          }
    return 0;
}

总结:

  1. 数组是使用下标来访问的,下标是从0开始。
  2. 数组的大小可以通过计算得到。

int arr[10];
int sz = sizeof(arr) / sizeof(arr[0]);

1.4 一维数组在内存中的存储

接下来我们探讨数组在内存中的存储。
看代码:

#include <stdio.h>
int main()
{
   int arr[10] = {0};
   int i = 0;
   int sz = sizeof(arr)/sizeof(arr[0]);
   for(i=0; i<sz; ++i)
      {
         printf("&arr[%d] = %p\n", i, &arr[i]);
      }
   return 0;
}

*(p + 1)指的是将p + 1的内存解引用,取p + 1内存里面的元素个数

int main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = &arr[0];
	for (i = 0; i < sz; ++i)
	{
		printf("%p = %p\n",p+i, &arr[i]);
	}
	return 0;
}

代码结果
内存连续存放

仔细观察输出的结果,我们知道,随着数组下标的增长,地址由低到高增长,元素的地址,也在有规律的递增。
由此可以得出结论: 数组在内存中是连续存放的。

2. 二维数组的创建和初始化

2.1 二维数组的创建

数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];

2.2 二维数组的初始化

数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
二维数组如果有初始化,行可以省略,列不能省略。

2.3 二维数组的使用

二维数组的使用也是通过下标的方式。
看代码:

#include <stdio.h>
int main()
{
	//int arr1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
	//int arr1[][4] = { {1,2},{3,4},{5,6} };
	//二维数组如果初始化,行是可以省略的,但是列不能
	//char arr2[5][6];
	//
	//1  2  3  4 
	//5  6  7  8
	//9 10 11 12
	//
	int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	//printf("%d\n", arr1[1][2]);
	int i = 0;
	for (i = 0; i < 3; i++)//0 1 2
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%-2d ", arr1[i][j]);
		}
		printf("\n");
	}

	return 0;
}

注意:%2d为右对齐,%-2d为左对齐。

2.4 二维数组在内存中的存储

像一维数组一样,这里我们尝试打印二维数组的每个元素。
看代码:

#include <stdio.h>
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;
}

结果如下
在这里插入图片描述
图片模拟形成过程
在这里插入图片描述

3. 数组越界

数组的下标是有范围限制的
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就
是正确的,
所以程序员写代码时,最好自己做越界的检查。

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
	}
	return 0;
}

二维数组的行和列也可能存在越界。

4. 数组作为函数参数

往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(这里要讲算法思想)函数将一个整形数组排序。
那我们将会这样使用该函数

4.1 冒泡排序函数的错误设计

#include <stdio.h>
void bubble_sort(int arr[])
{
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	//冒泡排序的趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		int j = 0;
		for (j = 0; j < sz - 1 - i; 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,5,9,2,4,7,6,8,0 };
	//排序 - 升序
	//冒泡排序

	bubble_sort(arr);//arr是数组首元素的地址

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

出问题,那我们找一下问题,调试之后可以看到 bubble_sort 函数内部的 sz ,是1。
难道数组作为函数参数的时候,不是把整个数组的传递过去?

4.2 数组名是什么?

#include <stdio.h>
int main()
{
int arr[10] = {1,23,4,5};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
//输出结果
return 0;
}
//数组的地址加1会跳过整个数组。
//数组首元素地址加1只会跳过一个元素

结论:

数组名是数组首元素的地址
但是有2个例外:
sizeof(数组名),数组名如果单独放在sizeof内部,这里的数组名表示整个数组,计算的是整个数组的大小。
&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
除此之外,遇到的所有的数组名都输数组首元素的地址。
数组的地址加1会跳过整个数组。
数组首元素地址加1只会跳过一个元素。

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0]+1);

	printf("%p\n", &arr);
	printf("%p\n", &arr+1);


	//printf("%d\n", sizeof(arr));//40
	return 0;
}

4.3 冒泡排序函数的正确设计

当数组传参的时候,实际上只是把数组的首元素的地址传递过去了。
所以即使在函数参数部分写成数组的形式: int arr[] 表示的依然是一个指针: int *arr 。
那么,函数内部的 sizeof(arr) 结果是4。

#include <stdio.h>
void bubble_sort(int *arr, int sz)
{
	int i = 0;

	//冒泡排序的趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		int j = 0;
		for (j = 0; j < sz - 1 - i; 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,5,9,2,4,7,6,8,0 };
	//排序 - 升序
	//冒泡排序
	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz);//arr是数组首元素的地址

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

如果这份博客对大家有帮助,希望各位给恒川一个免费的点赞作为鼓励,并评论收藏一下,谢谢大家!!!
制作不易,如果大家有什么疑问或给恒川的意见,欢迎评论区留言。
下期内容将会带来扫雷,三子棋等有趣游戏!

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

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

相关文章

java 学习3(数组)

java ——数组 ✍作者&#xff1a;电子科大不知名程序员 &#x1f332;专栏&#xff1a;java学习指导 各位读者如果觉得博主写的不错&#xff0c;请诸位多多支持&#xff1b;如果有错误的地方&#xff0c;欢迎在评论区指出 数组是一组相同类型元素按一定顺序排列的集合 数组相…

[MatLab]变量与数据结构

在开始工程之前&#xff0c;需要先指定工程目录&#xff0c;按住下图红框按钮进行选择。 Matlab分为编辑器和命令窗口&#xff0c;编辑器用来编写代码文件&#xff0c;而命令窗口可以实时交互。 在窗口中输入clc即可清除命令窗口&#xff1b;clear all可以清除工作区中所有变量…

【论文笔记】Long Tail Learning via Logit Adjustment

摘要 Our techniques revisit the classic idea of logit adjustment based on the label frequencies, either applied post-hoc to a trained model, or enforced in the loss during training. Such adjustment encorages a large relative margin between logits of rare …

项目管理系统的设计与实现

技术&#xff1a;Java、JSP等摘要&#xff1a;企业项目管理系统是为了使企业项目能够按照预定的成本、进度、质量顺利完成&#xff0c;而对人员、产品、过程和项目进行分析和管理的活动&#xff0c;系统主要包括项目基本信息操作、项目规划管理&#xff0c;合同管理&#xff0c…

一步一步教你如何使用 Visual Studio Code 编译一段 C# 代码

以下是一步一步教你如何使用 Visual Studio Code 编写使用 C# 语言输出当前日期和时间的代码&#xff1a; 1、下载并安装 .NET SDK。您可以从 Microsoft 官网下载并安装它。 2、打开 Visual Studio Code&#xff0c;并安装 C# 扩展。您可以在 Visual Studio Code 中通过扩展菜…

VMware NSX 4.1 发布 - 网络安全虚拟化平台

请访问原文链接&#xff1a;VMware NSX 4 - 网络安全虚拟化平台&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org VMware NSX 提供了一个敏捷式软件定义基础架构&#xff0c;用来构建云原生应用程序环境。NSX 专注于为具有异…

【SPSS】两配对样本T检验分析详细操作教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【微服务】-认识微服务

目录 1.1 单体、分布式、集群 单体 分布式 集群 1.2 系统架构演变 1.2.1 单体应⽤架构 1.2.2 垂直应⽤架构 1.2.3 分布式架构 1.2.4 SOA架构 1.2.5 微服务架构 1.3 微服务架构介绍 微服务架构的常⻅问题 1.4 SpringCloud介绍 1.4.1 SpringBoot和SpringCloud有啥关…

【Flutter入门到进阶】Flutter基础篇---介绍与环境

1 Flutter介绍 Flutter是谷歌公司开发的一款开源、免费的UI框架&#xff0c;可以让我们快速的在Android和iOS上构建高质量 App。它最大的特点就是跨平台、以及高性能。 目前 Flutter 已经支持 iOS、Android、Web、Windows、macOS、Linux等。 Flutter基于谷歌的dart语言&#…

NLTK与StanfordNLP工具包结合使用

(一) 概述 1.NLTK NLTK是一款著名的python自然语言处理工具包&#xff0c;其内收集了NLP领域大量的公开数据集以及常用模型&#xff0c;涵盖了分词&#xff0c;词性标注&#xff0c;命名实体识别&#xff0c;句法分析&#xff0c;依存分析等各种NLP领域的子任务。 2.Stanfor…

【Linux】动静态库-概念制作

文章目录前置知识:库的命名C标准库动静态库安装C/C静态库完整的库需要的东西制作静态库制作使用一个小疑惑:制作动态库制作使用总结:前置知识: 一般库分为两种:动态库和静态库 静态库和动态库本质就是文件&#xff01;也有inode 库的命名 库文件的命名一般为: libXXXXX.so 或…

基于部标JT808的车载视频监控需求与EasyCVR视频融合平台解决方案设计

一、方案背景 众所周知&#xff0c;在TSINGSEE青犀视频解决方案中&#xff0c;EasyCVR视频智能融合共享平台主要作为视频汇聚平台使用&#xff0c;不仅能兼容安防标准协议RTSP/Onvif、国标GB28181&#xff0c;互联网直播协议RTMP&#xff0c;私有协议海康SDK、大华SDK&#xf…

谷歌seo做的外链怎样更快被semrush识别

本文主要分享做谷歌seo外链如何能让semrush工具快速的记录并能查询到。 本文由光算创作&#xff0c;有可能会被剽窃和修改&#xff0c;我们佛系对待这种行为吧。 谷歌seo做的外链怎样更快被semrush识别&#xff1f; 答案是&#xff1a;多使用semrush搜索目标网站可加速爬虫抓…

SOLIDWORKS Premium 2023 SP1.0 三维设计绘图软件

SOLIDWORKS 中文完美正式版提供广泛工具来处理最复杂的问题,并提供深层技术完成关键细节工作。新功能可助您改善产品开发流程,以更快地将创新产品投入生产。Solidworks 是达索公司最新推出的三维CAD系统,它可让设计师大大缩短产品的设计时间,让产品得以快速、高效地投向市场…

2023年/2024届 暑期实习 【汇总+更新】

文章目录百度2024届暑期实习生招聘米哈游2023春季校园招聘正式启动&#xff08;含暑期实习&#xff09;拼多多2024届暑期实习生招聘百度2024届暑期实习生招聘 百度2023届校园招聘春季补录仍在持续进行中&#xff0c;本周日&#xff08;3月5日&#xff09;截止网申&#xff0c;…

ARM基础

文章目录1.ARM成长史1.1 ARM发展的里程碑11.2 ARM发展的里程碑21.3 ARM发展的里程碑31.4 ARM发展的里程碑42.ARM的商业模式和生态系统3.先搞清楚各种版本号3.1 ARM 的型号命名问题3.2 ARM 的几种版本号3.3 ARM型号的发展历程4.SoC和CPU的区别 & 外设概念的引入4.1 SoC和CPU…

面试问到不会的技术问题?大小公司?程序员、校招面试技巧

大家好&#xff0c;欢迎来到停止重构的频道。本期我们分享一下程序员面试的相关经验。可能是3月离职高峰&#xff0c;又或者毕业生准备找工作的缘故&#xff0c;最近有一些朋友问我们关于面试方面的经验。问题五花八门&#xff1a;面试总是紧张&#xff1f;项目、工作经验怎么介…

2023功能测试真的没有出路了吗?不会自动化测试的我留下了悔恨的泪水...

直接抛出我的结论&#xff1a;手工做业务类测试&#xff0c;没有前途。10K的工资已经是天花板 个人建议赶紧从业务测试跳出来&#xff0c;立即学习代码&#xff0c;走自动化测试方向。目前趋势&#xff0c;业务测试需要用自动化做。 为了让大家能够信服我的观点&#xff0c;本…

python-爬虫-字体加密

直接点 某8网 https://*****.b*b.h*****y*8*.com/ 具体网址格式就是这样的但是为了安全起见,我就这样打码了. 抛出问题 我们看到这个号码是在页面上正常显示的 F12 又是这样就比较麻烦,不能直接获取.用requests库也是获取不到正常想要的 源码的,因为字体加密了. 查看页面源代码…

开发一个会员管理系统

背景 由于现在公司内客户量剧增&#xff0c; 简单的靠电话及笔记本记录&#xff0c;来维护客户有些困难&#xff0c;但又不想去花钱购买那些专业版的会员管理系统&#xff0c;只能自己动手撸一个相对简易的会员系统来使用了。 开发语言及使用技术 后端&#xff1a;java、mys…