C语言 - 数组

news2025/4/8 13:07:57

目录

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

1.1 数组的创建

1.2 数组的初始化

1.3 一维数组的使用

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

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

2.1 二维数组的创建

2.2 二维数组的初始化

2.3 二维数组的使用

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

3. 数组越界

4. 数组作为函数参数

4.1 冒泡排序函数的设计

4.1.1 关于冒泡排序函数的错误设计

4.1.2 关于冒泡排序函数的正确设计

4.2 数组名是什么?

对于二维数组的数组名


我们原来要存放一个整数, 就会:

int a = 1;
int b = 2;
int c = 3;

那么如果要存放1~10, 或者要存放1~100呢? 如果创建10或100个变量就不方便了, 于是就有了数组的概念.

什么是数组? 数组是一组相同类型元素的集合.

那么C语言的数组形式是什么呢, 我们一起来看.

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

1.1 数组的创建

数组的创建方式:

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

数组创建的实例:

int arr[10];
char ch[5];
double data1[20];
double data2[15+5];

注: 数组创建,在C99标准之前,[]中要给一个常量或者常量表达式才可以,不能使用变量。在C99之后,数组的大小可以是变量,这是为了支持变长数组。

//下面的代码只能在支持C99标准的编译器上编译
int n = 10;
scanf("%d", &n);
int arr2[n];//这种数组是不能初始化

1.2 数组的初始化

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

数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。

//不完全初始化,剩余的元素默认初始化为0
int arr[10] = { 1,2,3 };
int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
int arr2[] = { 1,2,3 };

但是对于下面的代码要区分,内存中如何分配。

char ch1[10] = { 'a', 'b', 'c' };
//a b c 0 0 0 0 0 0 0
char ch2[10] = "abc";
//a b c \0 0 0 0 0 0 0
char ch3[] = { 'a', 'b', 'c' };
char ch4[] = "abc";

1.3 一维数组的使用

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

int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; 
//            0 1                9

当我们去访问上面这个数组的时候, 需要知道它在内存中的情况.

这段代码对应的是在内存中的栈区找了一块连续的空间, 在里面放了1~10.

那么我们可以通过下标引用操作符+下标编号来访问数组中的元素.

printf("%d\n", arr[4]);

如果要打印数组的每个元素:

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    //顺序打印
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    //逆序打印
    for (i = sz - 1; i >= 0; i--)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}
总结:
1. 数组是使用下标来访问的,下标是从0开始
2. 数组的大小可以通过计算得到。

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

在上面的代码中加入:

    for (i = 0; i < sz; i++)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }

可以看到数组的,每个元素的地址:

观察输出的结果,可以知道,随着数组下标的增长,元素的地址,也在有规律的递增.

由此我们得出: 数组在内存中是连续存放的.

那么我们同样也是可以通过调试在内存窗口中看到数组arr在内存中的分布情况.

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

二维数组相较于一维数组能够存放更多的数据. 它存在的原因就是因为相同的数据是可能会出现很多组. 像这种多组整数需要存储的话就可以考虑二维数组.

2.1 二维数组的创建

int arr[3][4];    // 第一个[]表示行, 第二个[]表示列. 3行4列.
char arr[3][5];
double arr[2][4];
可以看到在数组名后有两个 [], 对于第一行它表示的是三行四列的元素, 就像一个表格一样.
我们知道一维数组是一行, 而二维数组是有多行. 其实这就是一个概念.
比如说要存放下面这几组数据:
1 2 3 4
2 3 4 5
3 4 5 6

那么我们就可以创建如上文第一行代码的那样一个数组.

2.2 二维数组的初始化

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

可以看到, arr1第一行为1234, 第二行为2345, 第三行为3456. 因为我们前面已经限定了一行能放四个元素, 所以当第一行放了四个元素之后紧接着后面的初始化内容又找了四个给第二行, 再找四个给到第三行.
所以能看到如上图所示的现象.

那么如果初始化的数字不够数的时候, 会在后面初始化成0, 也如上图arr2和arr3所示.

2.3 二维数组的使用

二维数组的使用也是通过下标的方式.

#include <stdio.h>

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

运行结果:

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

前面在我们假想中的二维数组是多行多列的一个存在, 但是实际上在内存中并不是使用行列这种样子的存储方式, 而是连续的存储.

我们来进行验证, 打印二维数组每个元素的地址:

#include <stdio.h>

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

输出结果:

通过地址的变化可以观察出: 二维数组在内存中也是连续存放的.

于是, 我们可以进一步这样理解二维数组.

int arr[3][4];
理解为从第一个元素开始向后的连续12个空间, 看成是一个连续的一维数组, 有12个元素.
其实最终, 该代码与
int arr2[12];
在内存中的布局是一样的.
可以把二维数组理解为: 一维数组的数组.

3. 数组越界

数组的下标是有范围限制的。

数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。

所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。

所以程序员写代码时,最好自己做越界的检查。

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

4. 数组作为函数参数

往往我们在写代码的时候,会将数组作为参数传个函数,比如: 我要实现一个冒泡排序函数将一个整形数组排序.

冒泡排序的核心思想: 两个相邻的元素进行比较

代码思路:

4.1 冒泡排序函数的设计

4.1.1 关于冒泡排序函数的错误设计

int main()
{
    //数组
    //把数组的数据排成升序
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    //0 1 2 3 4 5 6 7 8 9
    int sz = sizeof(arr) / sizeof(arr[0]);
    //冒泡排序的算法,对数组进行排序
    bubble_sort(arr);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }

    return 0;
}
void bubble_sort(int arr[])
{
    //趟数
    int sz = sizeof(arr) / sizeof(arr[0]);
    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;
            }
        }
    }
}

执行上述代码之后, 会出问题, 并不能正确的将数据进行排序.

我们进行调试:

在调试到bubble_sort()中发现sz变成了1, 但是我们期望是10, 此时往下1-1=0, 并没有进行任何的对数据排序就退出了这个函数, 所以当整个程序执行完会发现并没有将数据进行排序就输出.

这是函数程序的编写中非常常见的错误.

4.1.2 关于冒泡排序函数的正确设计

//形参是数组的形式
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[] = { 9,8,7,6,5,4,3,2,1,0 };
    //0 1 2 3 4 5 6 7 8 9
    int sz = sizeof(arr) / sizeof(arr[0]);

    //冒泡排序的算法,对数组进行排序
    bubble_sort(arr, sz);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }

    return 0;
}
//形参是指针的形式
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;
            }
        }
    }
}

4.2 数组名是什么?

前面提到, 数组名是数组首元素的地址, 这个说法虽然对, 但是其实并不完全对, 有两个例外.

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节

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

int main()
{
    int arr[10] = {0};
    printf("%p\n", arr);//arr就是首元素的地址
    printf("%p\n", arr+1);
    printf("----------------------\n");
    printf("%p\n", &arr[0]);//首元素的地址
    printf("%p\n", &arr[0]+1);
    printf("----------------------\n");
    printf("%p\n", &arr);//数组 的地址
    printf("%p\n", &arr+1);

    //int n = sizeof(arr);//40
    //printf("%d\n", n);

    return 0;
}

执行结果:


对于二维数组的数组名

#include <stdio.h>

int main()
{
    int arr[3][4] = {0};

    printf("%d\n", sizeof(arr) / sizeof(arr[0]));//计算行
    printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));//计算列

    int sz = sizeof(arr);
    printf("%d\n", sz);    //48

    printf("%p\n", arr);//二维数组的数组名也表示数组首元素的地址(第一行的地址)
    printf("%p\n", arr+1);//第二行

    return 0;
}

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

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

相关文章

C++11 Thread线程库的使用

C11 Thread线程库的使用 传统的C&#xff08;C11标准之前&#xff09;中并没有引入线程这个概念&#xff0c;在C11出来之前&#xff0c;如果我们想要在C中实现多线程&#xff0c;需要借助操作系统平台提供的API&#xff0c;比如Linux的&#xff0c;或者windows下的 。 本文详细…

【数据结构】什么是算法

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法的定义 1.算法的概念 2.数据结构与算法的关系 二.算法的特性 输入 输出 有穷性 确定性 可行性 三.算法的设计要求 1.正确性 2.可读性 3.健壮性 4.效…

DALL·E 3 ChatGPT-4的梦幻联动

核心内容&#xff1a;DALLE 3 & ChatGPT-4的梦幻联动 hello&#xff0c;我是小索奇&#xff0c;最近DALL结合ChatGPT4的话题逐渐上升了起来&#xff0c;今天就带大家探索一下~ DALLE的主要功能是根据文本描述来生成图片。你可以告诉它一个穿着皮草的西瓜&#xff0c;它就能…

叠氮修饰的葡萄糖Ac4GIcNAz,98924-81-3

产品简介&#xff1a;The tetraacetylatedN-Azidoacetyl-glucosamine (Ac4GlcNAz) provides a non-radioactive alternativefor glycoconjugate visualization. It is cell-permeable, intracellularlyprocessed and incorporated instead of its natural monosaccharide count…

MongoDB——window11安装mongodb5.0.21版本服务端(图解版)

目录 一、mongodb官网下载地址二、安装步骤三、配置环境变量四、运行mongodb 一、mongodb官网下载地址 mongodb官网下载地址&#xff1a;https://www.mongodb.com/try/download/community 二、安装步骤 双击运行下载好的mongodb-windows-x86_64-5.0.21-signed.msi安装包&am…

JVM篇---第八篇

系列文章目录 文章目录 系列文章目录一、虚拟机为什么使用元空间替换了永久代?二、什么是Stop The World ? 什么是OopMap?什么是安全点?三、说一下JVM 的主要组成部分及其作用?一、虚拟机为什么使用元空间替换了永久代? 「什么是元空间?什么是永久代?为什么用元空间代…

定时任务详解

1、定时任务 在公司做项目时&#xff0c;经常遇到要用到定时任务的事情&#xff0c;但是对定时任务不熟练的时候会出现重复任务的情况&#xff0c;不深入&#xff0c;这次将定时任务好好学习分析一下 定时任务的原理 假如我将一个现场通过不断轮询的方式去判断&#xff0c;就…

【Gradle-10】不可忽视的构建分析

1、前言 构建性能对于生产力至关重要。 随着项目越来越复杂&#xff0c;花费在构建上的时间就越长&#xff0c;开发效率就越低。 通过分析构建过程&#xff0c;可以了解项目构建的时间都花在哪&#xff0c;以及项目存在哪些潜在的问题&#xff0c;找到构建瓶颈&#xff0c;解…

Qt之实现圆形进度条

在Qt自带的控件中&#xff0c;只有垂直进度条、水平进度条两种。 在平时做页面开发时&#xff0c;有些时候会用到圆形进度条&#xff0c;比如说&#xff1a;下载某个文件的下载进度。 展示效果&#xff0c;如下图所示&#xff1a; 实现这个功能主要由以下几个重点&#xff1a…

在公众号上怎么创建微信付费课程功能呢

微信付费课程功能是一项比较受欢迎的在线教育服务&#xff0c;可以帮助教育机构或个人更好地管理和销售课程资源&#xff0c;提高知识分享和变现的效率。下面将介绍如何创建微信付费课程功能。 一、了解微信付费课程功能 在创建微信付费课程功能之前&#xff0c;需要先了解微信…

【自学笔记】网络安全——黑客技术

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01;&#xff01;&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队…

【Java 进阶篇】HTML表格标签详解

HTML&#xff08;Hypertext Markup Language&#xff09;表格标签是在网页中用于创建表格的重要工具。表格是一种在网页上以行和列的方式组织和显示数据的有效方式。在本文中&#xff0c;我们将详细介绍HTML表格标签&#xff0c;包括如何创建表格、定义表头、单元格合并等内容。…

Flask实现注册登录模块

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言1.…

通过代码优雅地编写图表——Mermaid语法

通过代码优雅地编写图表——Mermaid语法 使用代码&#xff0c;在你的Typora中优雅地编写图表&#xff01; 先看一个示例&#xff1a; gantt dateFormat YYYY-MM-DD title Adding GANTT diagram to mermaid excludes weekdays 2023-01-10section A section Completed task …

快速了解SpringCloud Sleuth --链路追踪 + Zipkin--数据搜集/存储/可视化

&#x1f600;前言 本篇博文是关于SpringCloud Sleuth --链路追踪 Zipkin–数据搜集/存储/可视化的基本介绍和使用&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文…

常见源协议介绍

开源协议&#xff08;Open Source License&#xff09;是一种法律文档&#xff0c;用于规定如何使用、修改和分发开源软件和其他开源项目的规则和条件。这些协议允许创作者或组织将其创造的代码或作品以开放源代码的形式共享给他人&#xff0c;以促进协作、创新和知识共享。常见…

HttpClient实现爬虫开发

网络爬虫是一种高效获取网络信息的方式&#xff0c;而HttpClient是一个强大而灵活的Java库&#xff0c;提供了方便的API和丰富的功能&#xff0c;使其成为开发高效且灵活的网络爬虫的理想选择。本文将分享如何利用HttpClient库进行网络爬虫开发&#xff0c;帮助您更好地理解并实…

NSA 和 CISA 联合揭露当下十大网络安全错误配置

10月5日&#xff0c;美国国家安全局 (NSA) 和网络安全与基础设施安全局 (CISA) 公布了十大目前最常见的网络安全错误配置&#xff0c;这些错误由红蓝团队在大型组织网络中发现。 根据发布的联合报告&#xff0c;团队评估了国防部 (DoD)、联邦民事行政部门 (FCEB)、州和地方政府…

解决程序员百分百问题pip终极杀手

文章目录 pip中国版镜像源永久版中国镜像源pip添加多个中国版镜像源无敌版pip中的小细节 pip中国版镜像源 Python中使用pip安装包&#xff0c;常用的国内镜像有&#xff1a; 例如&#xff1a; Python中使用pip安装包&#xff0c;常用的国内镜像有&#xff1a;清华大学镜像&am…

Mac 点击桌面 出现黑边框 解决

1、桌面黑框效果 2、解决&#xff1a;设置为 仅在台前调度中