當前位置:網站首頁>C語言 數組(一維數組 · 二維數組)

C語言 數組(一維數組 · 二維數組)

2022-05-14 07:32:09牧瀬 紅莉棲

一、一維數組的創建和初始化

1.1 數組的創建:

數組是一組相同類型元素的集合。數組的創建方式:

type_t	arr_name 	[const_n];
// type_t 	指數組的元素類型
// arr_name 	數組的名稱
// const_n 	這是一個常量錶達式,用來指定數組的大小

數組創建的實例:

	int arr01[10];

	int i = 10;
	int arr02[i]; //數組是否可以正常創建?

	float arr03[3];
	double a04[50];

注:數組創建的時候,[ ]中要給一個常量才可以,不能使用變量。

1.2 數組的初始化:

數組的初始化是指,在創建數組的時候,給數組的內容同時賦值一些合理初始化值。

	int arr1[10] = {
     1,2,3 };
	int arr2[] = {
     1,2,3,4 };
	char arr3[3] = {
     'a',98,'c' };
	char arr4[] = {
     'a','b','c' };
	char arr5[] = "abcdef";

數組創建的時候,不指定數組大小就可以初始化,數組的元素個數根據初始化的內容來確定。
但是對於下面的代碼,要區分內存中如何分配。

	char ch1[5] = {
     'b','i','t' };
	char ch2[] = {
     'b','i','t' };
	char ch3[] = "bit";
	
	printf("%d\n", strlen(ch1));
	printf("%d\n", strlen(ch2));
	printf("%d\n", strlen(ch3));


如圖,strlen( ) 函數只是計算字符串大小,初始化只有三個字符,為什麼中間那個輸出15呢?

我們開啟調試查看一下三個 ch 字符數組的情况。

  1. 第一個 ch 字符數組,初始化五個空間,使用三個後,其他沒有使用的空間默認 ’ \0 ’ 結束標志,所以計算數組元素個數,顯示為3。
  2. 第二個 ch 字符數組,沒有初始化空間,那就根據數組元素個數分配空間。定義三個字符元素,但是沒有給出 ’ \0 ’ 結束標志,所以數組計算長度沒有及時結束,一直在內存中遇到某個 ’ \0 ’ ,程序才結束。
  3. 第三個 ch 字符串數組,同樣沒有初始化空間,但是這裏提供的是字符串數組,字符串末尾自帶 ’ \0 ’ ,所以正常結束,顯示為3。

二、一維數組的使用

對於數組的使用,我們之前介紹了一個操作符:[ ] ,下標引用操作符。它其實就是數組訪問的操作符。

//數組的使用
	int arr[10] = {
     0 }; //數組不完全初始化
	//計算數組元素個數
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	//循環賦值
	for (i = 0; i < 10; i++) {
    
		arr[i] = i;
	}
	//輸出數組的內容
	for (i = 0; i < 10; i++) {
    
		printf("%d", arr[i]);
	}

小結:

  1. 數組是使用下標來訪問的,下標是從0開始。
  2. 數組的大小可以通過計算獲得。

三、 一維數組在內容中的存儲

接下來我們探討下數組在內容中的存儲。

//數組在內存中的存儲
	int i = 0;
	int arr[10] = {
     0 };
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}

輸出結果如下:
在這裏插入圖片描述

仔細觀察輸出結果,我們會發現:

  1. 數組的每個元素間距都是相差4,這是因為我們定義的是int類型的數組。
  2. 隨著數組下標的增長,元素的地址,也會有規律的遞增。

由此可以得出結論:數組在內存中是連續存放的。


四、二維數組的創建和初始化

4.1 二維數組的創建

  1. 二維數組是兩個[ ],第一個[ ]控制行數,第二個[ ]控制列數(每行上有幾個元素)。

  2. 可以在{ }裏面套個{ },用來初始化每列上的元素。

  3. 可以省略第一個[ ],這樣程序會根據第二個[ ]判斷每行有幾個元素,然後進行初始化。
    但是第二個[ ]不能省略。

//二維數組的初始化
	int arr1[3][4] = {
     1,2,3,4 };
	int arr2[3][4] = {
     {
    1,2},{
    3,4} };
	int arr3[][4] = {
     1,2,3,4 };
	int arr4[][4] = {
     {
    1,2},{
    3,4} };

4.2 二維數組的使用

二維數組的使用也是通過下標的方式。

	int arr1[3][4] = {
     0 };
	int i = 0;
	//外層for,第一個[]控制行數
	for (i = 0; i < 3; i++) {
    
		int j = 0;
		//內層for,第二個[]控制列數
		for (j = 0; j < 4; j++) {
    
			//二維數組賦值
			arr1[i][j] = i * 4 + j;
		}
	}
	//輸出二維數組
	for (i = 0; i < 3; i++) {
    
		int j = 0;
		for (j = 0; j < 4; j++) {
    
			printf("arr1[%d][%d] = %d\n", i, j, arr1[i][j]);
		}
	}

五、 二維數組在內存中的存儲

像一維數組一樣,我們嘗試打印二維數組的每個元素。

//二維數組在內層中的存儲
	int arr[3][4];
	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]);
		}
	}

我們取二維數組地址輸出,發現二維數組在內存中存儲的地址也是連續的。
所以二維數組也是線性存儲的,不是像矩陣那樣有行有列。


六、數組作為函數參數

我們在編寫代碼的時候,有時候會把數組作為參數傳遞給函數,例如:我們現在要實現一個冒泡排序的函數,能把一個整型數組排序。

冒泡排序:把一個亂序的數組進行排序。
將數組的第一個元素和第二個元素對比,如果第一個元素比第二個大,就交換比特置;然後第二個比特置的元素和第三個比特置的元素比較,前一個大就交換比特置…一直到走完這一趟,會發現數組最後一個元素是數組中最大的元素。接下來就是下一趟比較,重複上述操作…

動圖演示:

在這裏插入圖片描述

了解了冒泡排序,讓我們回到數組作為函數參數,設計個能完成冒泡排序的函數。

6.1 冒泡排序函數的錯誤設計

//方法1:
#include <stdio.h>
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-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;
}

方法1,出現問題。調式我們發現,bubble_sort函數內部的sz是1。就是沒有成功計算出數組大小,導致函數不能完成排序。

難道數組作為函數參數的時候,不是把整個數組傳遞過去?


6.2 數組名是什麼?

讓我們取數組名的地址看一下。

	int arr[10] = {
     1,2,3,4,5 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	printf("%d\n", *arr);


看下輸出結果,我們可以發現,數組名和數組首元素地址是一樣的。數組名就是數組首元素地址

但是若數組名是首元素地址,那麼我們計算一下數組名。

	int arr[10] = {
     1,2,3,4,5 };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr[0]));


為什麼輸出的結果是:40和4?不是說兩個的地址是一樣的嗎?

因為==數組名是數組首元素的地址。==有兩個例外

  1. sizeof(數組名),計算整個數組的大小,sizeof內部單獨放一個數組名,數組名錶示整個數組。
  2. 取地址符號&。&數組名的組合,取出的是數組的地址。&數組名,數組名錶示整個數組。

除了這兩種情况之外,所有的數組名都錶示數組首元素的地址。


6.3 冒泡排序函數的正確設計

之前我們簡單的把數組名作為函數參數傳遞過去,實際上只是把數組首元素地址傳遞過去而已。
所以之後我們在sizeof()計算數組大小

int sz = sizeof(arr) / sizeof(arr[0])
只是把傳遞過來的數組(實際上是數組首元素地址),除於數組首元素地址。
自己除於自己,結果sz等於1.
//冒泡排序
//bubble_sort方法
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 - i - 1; j++) {
    
			if (arr[j] > arr[j + 1]) {
    
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

//main方法
	int i = 0;
	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\n", arr[i]);
	}

版權聲明
本文為[牧瀬 紅莉棲]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205140613192325.html

隨機推薦