主頁 > 軟體設計 > 【C語言基礎學習筆記】四、陣列詳解(超詳細!超硬核!)

【C語言基礎學習筆記】四、陣列詳解(超詳細!超硬核!)

2021-05-02 19:06:01 軟體設計

本章前言
在程式設計中,為了處理方便,把具有相同型別的若干變數按有序的形式組織起來,這些按序排列的同類資料元素的集合稱為陣列,在C語言中,陣列屬于構造資料型別,一個陣列可以分解為多個陣列元素,這些陣列元素可以是基本資料型別或是構造型別,因此按陣列元素的型別不同,陣列又可分為數值陣列、字符陣列、指標陣列、結構陣列等各種類別,
簡化記憶方式:陣列是一組相同型別元素的集合,


文章目錄

  • 一維陣列的創建和初始化
      • 一維陣列的創建
      • 一維陣列的初始化
      • 一維陣列的使用
      • 一維陣列在記憶體中的存盤
  • 二維陣列的創建和初始化
      • 二維陣列的創建
      • 二維陣列的初始化
      • 二維陣列的使用
      • 二維陣列在記憶體中的存盤
  • 陣列作為函式引數
  • 思考:陣列名到底是什么?
  • 三維陣列及多維陣列


一維陣列的創建和初始化

一維陣列的創建

陣列的創建方式 :

type_t arr_name[const_n];
//type_t是指陣列的元素型別
//arr_name是陣列名
//const_n是一個常量運算式,用來指定陣列的大小

注∶陣列創建,[ ]中要給一個常量才可以,不能使用變數,
例如:

//代碼1 
int arr1[10];
char arr2[9];
double arr3[8];
//以上陣列可正常創建

//代碼2
int count = 10;
int arr4[count];
//該陣列不能正常創建,[]中應該為常量,不能為變數

提示:有些編譯器中[ ]中出現了變數不報錯,也正常編譯執行,那是因為該編譯器支持C99語法標準,在C99語法標準中有變長陣列的概念-- -
陣列[]中可以是變數,
一般我們常用的編譯器,如Viual Studio(VS)系列編譯器是不支持C99語法標準的,


一維陣列的初始化

陣列的初始化是指,在創建陣列的同時給陣列的內容一些合理初始值,

int arr1[10] = { 1,2,3 };//不完全初始化
int arr2[] = { 1,2,3,4 };
int arr3[5] = { 12345 }; //完全初始化
char arr4[3] = i'a ', 98'c'};
char arr5[] = { 'a ', ' b', 'c ' };
char arr6[] = "abcdef";

在這里插入圖片描述
這里我們要注意區分

char ch2[] = { 'b','i','t' };
char ch4[] = "bit";

在這里插入圖片描述

在使用printf列印字符以及strlen求字串長度時候,遇到’\0’才停止,沒遇到’\0’之前不停止,


一維陣列的使用

對于陣列的使用我們之前介紹了一個運算子︰[ ]下標參考運算子,它其實就陣列訪問的運算子,我們來看代碼︰

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };//陣列的不完全初始化//計算陣列的元素個數
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	//對陣列內容賦值,陣列是使用下標來訪問的,下標從0開始,
	for (i = 0; i < 10; i++)//這里寫10,好不好?
		arr[i] = i;
	//輸出陣列的內容
	for (i = 0; i < 10; ++i)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

在這里插入圖片描述

總結:
1.陣列是使用下標來訪問的,下標是從O開始,
2.陣列的大小可以通過計算得到,
int arr[10]; int sz = sizeof(arr) / sizeof(arr[0]);


一維陣列在記憶體中的存盤

接下來我們探討陣列在記憶體中的存盤,看下圖︰
在這里插入圖片描述

通過觀察我們可以看到:
1.一維陣列在記憶體中是連續存放的
2.隨著陣列下標的增長,地址是由低到高變化的

在這里插入圖片描述
陣列地址連續存放有什么實際意義或作用嗎?
看下面這個例子:
在這里插入圖片描述
這個例子可以很好說明剛剛的問題,正因為陣列是連續存放的,通過陣列首元素的地址往后找可以找到每一個陣列對應的元素!


二維陣列的創建和初始化

二維陣列的創建

//二維陣列創建
int arr1[3][4];
char arr2[3][4];
double arr3[4][5];

當我們創建一個二維陣列int arr[3][4]后,在我們的腦海中要形式對應的三行四列二維陣列,這個陣列的每個元素都是int型別,(二維陣列有行列之分)
在這里插入圖片描述


二維陣列的初始化

//初始化---創建的同時給賦值
方式①
int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//完全初始化

在這里插入圖片描述

三行四列的陣列arr1有12個元素,我們可以在初始化的時候直接用大括號將12個元素括起來賦值給arr1,


思考:如果說我們給的元素個數大于12個或小于12個會發生什么呢?
(1)大于12個元素時:程式運行時,編譯報錯,無法正常執行,報錯原因就是初始值設定項太多,從這個報錯我們大概就能知道對于陣列創建,編譯器會檢查初始項是否大于陣列的長度,這個其實也很好理解,陣列本質也是變數,變數的創建需要向記憶體申請空間,如果初始值設定項占用的空間大于陣列申請的空間,就會“越界訪問”(比如陣列申請一塊40個位元組大小的空間,我們在設定初始項的時候給了11個int型別的值,也就是44個位元組,超過陣列本身可以訪問空間的大小了),
在這里插入圖片描述
(2)小于12個元素時:陣列會進行不完全初始化,前幾項會賦值成初始化的值,后面幾項會自動賦初始值0填充,(如果是字符陣列,會用\0填充,\0的ASCII碼值是0)
在這里插入圖片描述


方式②
二維陣列可以看作由多個一維陣列組成,所以我們可以這樣初始化:
int arr1[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
在這里插入圖片描述
(1)在使用方式②初始化int arr1[3][4]時,如果初始的行或者列超限會怎么樣呢?
可以看到會出現類似方式①越界的問題,這個其實也比較好理解,int arr[3][4],二維陣列arr是一個三行四列的形式,其實將二維陣列arr[3][4]看作有三個一位陣列arr[4]組成的陣列,這個陣列有三個元素,每個元素都是由四個元素組成的陣列,如果初始的行或者列超限就會導致類似方式①說到的越界訪問的問題,所以報錯編譯不過去!
在這里插入圖片描述
(2)初始化的時候不完全賦值會怎么樣呢?
陣列會進行不完全初始化,前幾項會賦值成初始化的值,后面幾項會自動賦初始值0填充,(如果是字符陣列,會用\0填充,\0的ASCII碼值是0)
在這里插入圖片描述
注意:二維陣列在創建的時候行可以省略,列不能省略(第一個[ ]中的值可以不寫,第二個[ ]值必須寫)
在這里插入圖片描述


二維陣列的使用

二維陣列的使用方式也是通過下標的方式,二維陣列的行和列下標都是從0開始的:
在這里插入圖片描述

#include<stdio.h>
int main()
{
	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%3d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在這里插入圖片描述


二維陣列在記憶體中的存盤

之前我們提到在創建二維陣列的時候,會在腦海中將其想象成一個二維表(有行和列),但是二維陣列在記憶體的存盤形式是什么樣的呢?跟我們剛剛想的二維表形式一樣存盤方式嗎?
為了研究二維陣列的存盤,這里我們可以嘗試將二維陣列的每個元素都列印出來:
在這里插入圖片描述
我們可以看到二維陣列的每個元素之間均相差4個位元組,所以二維陣列在記憶體中也是連續存放的!
這個連續存放有兩層含義:1.每一行內部的元素連續存放 2.行與行之間連續存放
在這里插入圖片描述


思考:了解二維陣列在記憶體中是連續存放的有什么作用?
1、在說int arr[][4]; 這個例子的時候,我們說二維陣列行可以省略,列不可以省略,為什么列不可以省略呢?
當列確定的時候,我們才能知道一行有多少個元素,才能知道第二行從哪里開始,否則的話,這個二維陣列就不是確定的
2、只有當二維陣列是連續存放的方式,當我拿到二維陣列首元素地址的時候,就可以依次訪問到這個陣列的所有元素,
在這里插入圖片描述
二維陣列arr[3][4]可以看作由三個一維陣列組成,這三個一位陣列的陣列名分別為arr[0], arr[1], arr[2]
在這里插入圖片描述

陣列通過陣列名 + [下標]訪問其成員,由此我們可知arr[0], arr[1], arr[2]也是陣列名,
該二維陣列的陣列名:arr
二維陣列的第一行陣列名:arr[0]
二維陣列的第二行陣列名:arr[1]
二維陣列的第三行陣列名:arr[2]


陣列作為函式引數

我們在寫代碼的時候,往往會將陣列作為引數傳給函式,比如:我們要實作一個冒泡排序函式將一個整型陣列排序,那我們將這樣使用函式:

冒泡排序的思想:兩兩相鄰的元素進行比較,并且可能的話需要交換,

在這里插入圖片描述

一趟解決一個數字的排序問題,第一趟最大值9出現到最右側,第二趟8到右側第二位
10個數字,需要進行9躺冒泡排序
n個數字,需要進行 n - 1躺

一趟冒泡排序內部:
第一趟:10個數字待排序,9對比較
第二趟:9個數字待排序,8對比較
第三趟:8個數字待排序,7對比較
……
第九趟:2個數字待排序,1對比較

代碼實作:

#include<stdio.h>
void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)//確定冒泡排序的趟數
	{
		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 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:");
	print(arr, sz);
	//冒泡排序,進行升序排列
	bubble_sort(arr, sz);
	printf("排序后:");
	print(arr, sz);
	return 0;
}

在這里插入圖片描述

冒泡排序法優化:當我們要排序的陣列本身就是有序的時候,或者說陣列排序的時候排好前幾項就已經有序了,這時候按照上面的方法還要進行兩兩比較,效率就比較低,對此我們進行想要的優化,

#include<stdio.h>
void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < sz - 1; i++)//確定冒泡排序的趟數
	{
		int flag = 1;//用于判斷比較是否繼續
		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;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:");
	print(arr, sz);
	//冒泡排序,進行升序排列
	bubble_sort(arr, sz);
	printf("排序后:");
	print(arr, sz);
	return 0;
}

思考:陣列名到底是什么?

我們經常會說陣列名是首元素地址,那么這個說法對不對呢?這里我們可以驗證一下,
在這里插入圖片描述
可以看到兩者一樣,所以陣列名是首元素地址,

但是要排除以下兩種情況:
①sizeof(陣列名)-- - 陣列名表示整個陣列-- - 計算的是整個陣列的大小,單位是位元組
② &陣列名-- - 陣列名表示整個陣列-- - 取出的是整個陣列的地址
除上述兩種情況以外,其余情況陣列名均表示首元素地址!


陣列地址和陣列首元素地址有什么區別?

兩者的地址值是一樣的,但是含義和使用不同,
陣列地址 + 1表示跳過整個陣列,首元素地址 + 1表示跳到第二個元素,
在這里插入圖片描述

& arr + 1 與 & arr 相差40個位元組
arr + 1 與 arr相差4個位元組


三維陣列及多維陣列

三維陣列具有高、寬、深的概念,或者說行、列、層的概念,即陣列嵌套陣列達到三維及其以上,是最常見的多維陣列,由于其可以用來描述三維空間中的位置或狀態而被廣泛使用,
三維陣列就是維度為三的陣列,可以認為表示對該陣列存盤的內容使用了三個獨立參量去描述,但更多的是認為該陣列的下標是由三個不同的參量組成的,三維陣列又被認為是二維陣列的陣列,而二維陣列也可以認為是一維陣列的陣列,
陣列這一概念主要用在撰寫程式當中,和數學中的向量、矩陣等概念有一定的差別,主要表現在陣列內的元素可以是任意的相同資料型別,包括向量和矩陣,
對陣列的訪問一般是通過下標進行的,在三維陣列中,陣列的下標是由三個數字構成的,通過這三個數字組成的下標對陣列的內容進行訪問,
多維陣列:三維或者三維以上的陣列,
定義方式:type name[size1][size2]…[sizeN];
例如,下面的宣告創建了一個三維 4 . 3 . 2 整型陣列:
int threedim[4][3][2];

在這里插入圖片描述
就目前學習而言,很少使用到三維及以上陣列形式,所以就不在進行進一步的研究和說明,對其有個大概的了解和認識即可!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/282150.html

標籤:其他

上一篇:快速開平方根倒數演算法(Fast inverse square root)的一點探究

下一篇:2021第十二屆藍橋杯C++ B組第一場省賽賽后總結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more