C语言数组详解

一维数组

创建和初始化

数组就是一组相同元素的集合。

他的创建:

char arr[10];
int arr1[5];

数组创建中 [] 里不能是变量,但是在c99标准之后就可以了被称为变长数组,但是不常用,而且变长数组不能初始化。

初始化:

//数组的初始化
int main()
{int arr[10] = { 1,2,3,4,5 };//不完全初始化,剩下的都是0int arr1[] = { 1,2,3,4 };int arr2[10] = { 0 };int arr3[] = { 0 };//这两种是不一样的初始化,arr2是十个元素,arr3是一个
}

创建数组的时候,如果不想指定 [] 的大小,就得初始化,数组的元素个数由初始化内容确认,例如:arr1,他的元素个数就是四个。

数组 arr 属于不完全初始化,但是他的元素个数还是10个,只不过剩下的初始化为0了。

arr2 和 arr3 要区分,他们的元素个数是不一样的。

一维数组的使用

//一维数组的使用
int main()
{int arr[10];int sz = sizeof(arr) / sizeof(arr[0]);printf("%d\n", sz);for (int i = 0; i < sz ; i++){arr[i] = i;}	for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}

这个代码第一个循环我们可以自己初始化数组里的内容,第二个循环输出数组。我们用  sizeof(arr) / sizeof(arr[0]  可以来计算数组里有多少个元素。

总结:1.数组里的元素个数可以计算。

            2.数组使用下标来访问,下标从0开始。

一维数组在内存中的存储

//一维数组在内存中的存储
int main()
{int arr[10];int sz = sizeof(arr) / sizeof(arr[0]);//printf("%d\n", sz);for (int i = 0; i < sz ; i++){arr[i] = i;}for (int i = 0; i < sz; i++){printf("%p\n", &arr[i]);}
}//四个字节的存储因为是int类型   连续存储  随下标的增长地址从低到高

我们可以看到一维数组在内存中是连续存储的,而且每个地址都差四个,因为数组类型是 int ,int类型是四个字节的存储,每个字节都有一个地址,所以差四个。而且随下标的增长地址从低到高

二维数组

创建和初始化

创建:

char arr[2][3];
int arr1[3][4];

初始化:

int main()
{//      行 列int arr[2][3] = { {1,2,3},{4,5,6} };int arr1[2][3] = { 1,2,3,4,5,6 };//编译器会自己把他们分开int arr2[2][3] = { {1,2},{3,4} };//不完全初始化int arr3[][3] = { {1,2,3 }, {4, 5, 6} };//行可以省略,列不可以。
}

其实二维数组可以理解成几个一维数组的集合。我们可以调试看看他们存储的值:

看到 arr1 确实编译器给他分开了,二维数组的不完全初始化也会补0。

二维数组的使用

//二维数组的使用
int main()
{int arr[2][3] = { 1,2,3,4,5,6 };int i = 0;for (i = 0; i < 2; i++){int j = 0;for (j = 0; j < 3; j++){printf("%d ", arr[i][j]);}}
}

二维数组在内存中的存储

//二维数组内存中的存储
int main()
{int arr[2][3] = {1,2,3,4,5,6};int i = 0;for (i = 0; i < 2; i++){int j = 0;for (j = 0; j < 3; j++){printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);//也是连续存储的,随下标的增长地址从低到高}}
}

可以看到二维数组和一维数组在内存中存储的方式一样,连续存储,差四个字节,随下标地址从低到高。

数组越界

int main()
{int arr[10];int sz = sizeof(arr) / sizeof(arr[0]);printf("数组里有%d个元素\n", sz);for (int i = 0; i < sz ; i++){arr[i] = i;}	for (int i = 0; i <= sz; i++){printf("%d ", arr[i]);}
}

我就用一维数组的代码,做了修改,让 i <= sz ,这样 i  会等于 10 ,这样就数组越界了。

超出了数组合法空间的访问,但是编译器不报错,但是不代表代码就是正确的。所以使用时自己最好检查,二维数组也会越界。

数组名的不同意义

为了探讨数组名的意义,我们看一个冒泡排序的函数:(不知道冒泡排序可以关注我,我后面会讲解

//函数错误版本:数组传参的数组名是什么,是首元素的地址。
void sort(int arr[])
{int sz = sizeof(arr) / sizeof(arr[0]);//所以怎么计算sz都等于1.因为地址都是等于四个字节的for (int i = 0; i < sz - 1; i++){for (int j = 0; j < sz - 1 - i; j++){if (arr[j] < arr[j + 1]){int tem = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tem;}}}
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };sort(arr);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}
}

我们需要把数组的元素从大到小打印出来,我们看看这个代码的结果:

他没有完成我们的任务,为什么会这样?

这样我们打印sz 的值看看

发现 sz是1,但是我们不是让他计算数组的元素个数吗,为什么会是1呢,就是因为我们函数传参的时候传的是数组名,这里的数组名代表的是数组的首元素地址,而地址的大小永远都是 4 /  8  

个字节。

所以我们正确的样子是:

//函数正确版本:
void sort(int arr[],int sz)
{//int sz = sizeof(arr) / sizeof(arr[0]);//给他换到主函数里for (int i = 0; i < sz - 1; i++){for (int j = 0; j < sz - 1 - i; j++){if (arr[j] < arr[j + 1]){int tem = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tem;}}}
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);sort(arr,sz);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}
}

通过这个例子我们就发现数组名是首元素地址的意义。

当然有两个例外:1 . sizeof( 数组名 ) 这里计算的计算整个数组的大小

2. &数组名,这里也是取出的整个数组的地址。

但是整个数组的地址在数字上和首元素地址相同,给他们分别加1 就可以看出区别了:

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅聊什么是Redis?

需求&#xff1a;MySQL面临大量的查询&#xff0c;即读写操作&#xff0c;因此类比CPU&#xff0c;给数据加缓存&#xff0c;Redis诞生。应用程序从MySQL查询的数据&#xff0c;在Redis设置缓存&#xff08;记录在内存中&#xff0c;无需IO操作&#xff09;&#xff0c;后再需要…

8.list容器的使用

文章目录 list容器1.构造函数代码工程运行结果 2.赋值和交换代码工程运行结果 3.大小操作代码工程运行结果 4.插入和删除代码工程运行结果 5.数据存取工程代码运行结果 6.反转和排序代码工程运行结果 list容器 1.构造函数 /*1.默认构造-无参构造*/ /*2.通过区间的方式进行构造…

AJAX —— 学习(二)

目录 一、利用 JSON 字符串 返回数据 &#xff08;一&#xff09;基础代码 &#xff08;二&#xff09;原理及实现 二、nodmon 工具 自动重启服务 &#xff08;一&#xff09;用途 &#xff08;二&#xff09;下载 &#xff08;三&#xff09;使用 三、IE 缓存问题 &a…

计算机网络:数据链路层 - 可靠传输协议

计算机网络&#xff1a;数据链路层 - 可靠传输协议 可靠传输概念停止-等待协议 SW回退N帧协议 GBN选择重传协议 SR 可靠传输概念 如下所示&#xff0c;帧在传输过程中受到干扰&#xff0c;产生了误码。接收方的数据链路层&#xff0c;通过真伪中的真检验序列 FCS 字段的值&…

Python环境下基于离散小波变换的信号降噪方法

Mallat创造了小波分析中的经典理论之一&#xff0c;即多分辨率分析的概念。后来&#xff0c;在Mallat与Meyer的共同努力之下&#xff0c;他们又在这一理论的基础上发明了离散小波变换的快速算法&#xff0c;这就是Mallat塔式算法&#xff0c;这种算法可以大量减少计算时间。在之…

6、Cocos Creator 2D 渲染组件:​Sprite 组件​

Sprite 组件 Sprite&#xff08;精灵&#xff09;是 2D/3D 游戏最常见的显示图像的方式&#xff0c;在节点上添加 Sprite 组件&#xff0c;就可以在场景中显示项目资源中的图片。 属性功能说明Type渲染模式&#xff0c;包括普通&#xff08;Simple&#xff09;、九宫格&#x…

Android Monkey自动化测试

monkey一般用于压力测试&#xff0c;用户模拟用户事件 monkey 基本用法 adb shell monkey [参数] [随机事件数]monkey常用命令 -v&#xff1a;用于指定反馈信息级别&#xff0c;总共分三个等级-v -v -vadb shell mokey -v -v -v 100-s&#xff1a;用于指定伪随机数生成器的种…

Apache DolphinScheduler 【安装部署】

前言 今天来学习一下 DolphinScheduler &#xff0c;这是一个任务调度工具&#xff0c;现在用的比较火爆。 1、安装部署 1.0、准备工作 1.0.1、集群规划 dolphinscheduler 比较吃内存&#xff0c;所以尽量给 master 节点多分配一点内存&#xff0c;桌面和虚拟机里能关的应用…

HomePlug AV

目录 HomePlug AV的基本概念基本术语网络概念网络实例 HomePlug AV物理层&#xff08;PHY&#xff09;HomePlug AV OFDM收发器架构PHY的调制模式FC调制和ROBO调制物理层的特点OFDM频域/时域转换开窗/槽式OFDM信号和噪声PHY发送控制——信道自适应PHY帧格式&#xff08;Symbol&a…

jupyter Notebook 默认路径修改

1. anaconda prompt 中运行 jupyter notebook --generate-config 命令&#xff0c;将在 C:\Users\Think\.jupyter文件下生成 jupyter_notebook_config.py 文件。 2.在jupyter_notebook_config.py 文件中&#xff0c;找c.NotebookApp.notebook_dir 这个变量&#xff0c; (1)若…

【Linux】详解动态库链接和加载对可执行程序底层的理解

一、动静态库链接的几种情况 如果我们同时提供动态库和静态库&#xff0c;gcc默认使用的是动态库。如果我们非要使用静态库&#xff0c;要加-static选项。如果我们只提供静态库&#xff0c;那可执行程序没办法&#xff0c;只能对该库进行静态链接&#xff0c;但程序不一定整体…

MySQL版本特性和存储引擎选择

MySQL版本特性和存储引擎选择 1.说一下MySQL 5.5 5.6 5.7 8.0 各个版本的特性 MySQL 5.5 优点: 稳定性&#xff1a;5.5版本是长期支持&#xff08;LTS&#xff09;版本&#xff0c;因此它非常稳定&#xff0c;被广泛部署在生产环境中。兼容性&#xff1a;与旧版本的MySQL和…

Golang | Leetcode Golang题解之第3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; func lengthOfLongestSubstring(s string) int {// 哈希集合&#xff0c;记录每个字符是否出现过m : map[byte]int{}n : len(s)// 右指针&#xff0c;初始值为 -1&#xff0c;相当于我们在字符串的左边界的左侧&#xff0c;还没有开始移动r…

【C++常用函数介绍】isalpha,isalnum、isdigit、islower、isupper 用法

首先 isalpha,isalnum、isdigit、islower、isupper 的使用方法都需要用到一个头文件 #include<ctype.h>其次 系统的介绍以上函数的用法 isalpha()用来判断一个字符是否为字母 isalnum&#xff08;&#xff09;用来判断一个字符是否为数字或者字母&#xff0c;也就是说…

【数据结构】——二叉树的递归实现,看完不再害怕递归

创作不易&#xff0c;感谢三连加支持&#xff1f;&#xff01; 一 递归理解 递归无非就是相信它&#xff0c;只有你相信它&#xff0c;你才能写好递归&#xff01;为什么&#xff1f;请往下看 在进入二叉树的实现之前&#xff0c;我们得先理解一遍递归&#xff0c;可能很多…

Android JNI 调用第三方SO

最近一个项目使用了Go 编译了一个so库&#xff0c;但是这个so里面还需要使用第三方so库pdfium, 首先在Android工程把2个so库都放好 在jni中只能使用dlopen方式&#xff0c;其他的使用函数指针的方式来调用&#xff0c;和windows dll类似&#xff0c;不然虽然编译过了但是会崩溃…

SpringBoot -- 外部化配置

我们如果要对普通程序的jar包更改配置&#xff0c;那么我们需要对jar包解压&#xff0c;并在其中的配置文件中更改配置参数&#xff0c;然后再打包并重新运行。可以看到过程比较繁琐&#xff0c;SpringBoot也注意到了这个问题&#xff0c;其可以通过外部配置文件更新配置。 我…

Android Studio控制台输出中文乱码问题

控制台乱码现象 安卓在调试阶段&#xff0c;需要查看app运行时的输出信息、出错提示信息。 乱码&#xff0c;会极大的阻碍开发者前进的信心&#xff0c;不能及时的根据提示信息定位问题&#xff0c;因此我们需要查看没有乱码的打印信息。 解决步骤&#xff1a; step1: 找到st…

RUST语言变量与数据类型使用

使用之前了解: fn main() 表示程序入口点 println!("要输出的内容"); 表示格式化输出 变量与常量声明: let 变量:变量类型 变量值;let mut 变量:变量类型 变量值; const 常量:常量类型 常量值 如果 声明时不指定类型,将根据赋值类型自动推导 变量类型参与下…

词向量模型评估

一、既有范式 词向量的语言学特性&#xff1a;这部分主要通过一些具体的指标来评估词向量是否能捕捉到语言的内在规律&#xff0c;包括&#xff1a; 相似度评价指标&#xff1a;检查词向量空间中距离近的词是否与人类直觉一致&#xff0c;例如&#xff0c;利用余弦相似度来评估…