詳解C語言中的數組

數組的定義

首先定義一個變量,來存儲一個人的年齡,例如:

#include<stdio.h>			//頭文件	

void main()					//程序入口
{
	int age = 20;			//定義變量age並儲存值爲18
	
	return;					//程序結束
}

這沒什麼困難,但要是現在要求我們儲存20個人呢?如果一個一個去定義,那豈不是很浪費時間,這個時候,我們就可以使用數組了。

數組其實就是把一堆數據定義到一塊了,然後起一個名字,定義一個數據類型。

數組的格式:
數據類型 變量名[常量]={x,y,z};

例如:

#include<stdio.h>							//頭文件

void main()									//程序入口
{
	int age [20]={1,2,3,4,5,6,7,8,9,10};	//定義數組
	
	return;									//程序結束
}

這裏需要說一下,爲什麼定義數組要用常量而不是變量,下面的這個例子不可以碼?

#include<stdio.h>				//頭文件	

void shuzu(int x)				//定義函數 
{
	int age[x];					//定義變量age
	
	return;						//函數結束
}
void main()						//程序入口
{
	shuzu(20);					//調用函數並傳值
	
	return;						//程序結束
}

上面這塊代碼,從邏輯上看起來好像沒什麼毛病,但是這麼寫是不行的,我們反彙編一下正常的程序就明白了:
在這裏插入圖片描述
這裏可以看到,我們要求age可以存20個數,所以堆棧提升了90,但是如果我們用變量的話,程序就不知道我們要存多少個數,堆棧就無法提升,反彙編生成不了,自然就會報錯了。

那麼如果我們傳值會堆棧怎麼樣呢:

#include<stdio.h>							//頭文件

void main()									//程序入口
{
	int age [20]={1,2,3,4,5,6,7,8,9,10};	//定義數組並傳值
	
	return;									//程序結束
}

看一下反彙編:
在這裏插入圖片描述
可以看到,最先存進去的參數,地址編號最少。

數組的內存分配

如果我們把程序的函數據結構定義成char,看一下堆棧中會有什麼變化:

#include<stdio.h>							//頭文件

void main()									//程序入口
{
	char age [20];							//定義數組
	
	return;									//程序結束
}

看一下反彙編:
在這裏插入圖片描述

90-54=36 = 54

這裏相對於之前的90減少54,也就是說,同樣的程序,不同類型,它少分配了36,這裏用的是char,但是爲啥要少分配36呢,這是因爲每臺電腦的本機寬度不同,我這裏是32位操作系統,處理4字節的程序比處理2字節的程序要方便,所以它4個字節的減少。

數組的讀寫

假如我們要往定義的數組裏存值,我們可以這樣寫:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int age[5];			//定義數組age,可以存儲5個數
	
	age[0] = 1;			//往數組的第一位存一個1
	age[1] = 2;			//往數組的第二位存一個2
	age[2] = 3;			//往數組的第三位存一個3

	return;				//程序結束
}

看一下堆棧:
在這裏插入圖片描述
跟之前統一傳值是一樣的。

數據存進去了我們也要讀,那麼怎麼讀數據呢,例如:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int age[5];			//定義數組age,可以存儲5個數
	int r;

	age[0] = 1;			//往數組的第一位存一個1
	age[1] = 2;			//往數組的第二位存一個2
	age[2] = 3;			//往數組的第三位存一個3

	r = age[1];				//讀取age數組裏的第二個數			
	printf("%d \n",r);		//把讀出來的數輸出到控制檯

	return;					//程序結束
}

運行結果:
在這裏插入圖片描述
當然,我們還可以這麼取值:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int age[5] = {1,2,3,4,5};			//定義數組age,可以存儲5個數
	
	int r;								//定義變量
	int x;
	
	x = 0								//變量賦值
	r = age[x];							//讀取age數組裏的第x個數			
	printf("%d \n",r);					//把讀出來的數輸出到控制檯

	return;								//程序結束
}

這裏可以用x,就可以用x+y,x+1等等,只要你能返回一個結果,這個結果不超出數組的長度,那麼值就可以取出來,這裏就不一一舉例了,原理是相通的,運行結果:
在這裏插入圖片描述
注:定義數組的時候,必須是常量,而使用數組的時候,可以是變量。

讀取越界

什麼叫越界呢,就是你讀取的數超過了你定義數組的長度,例如:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int age[5] = {1,2,3,4,5};		//定義數組age,可以存儲5個數
	int r;
	int x;
	

	x = 15;					//讀第16個數,這裏就越界了
	r = age[x];				//讀取age數組裏的第x個數			
	printf("%d \n",r);		//把讀出來的數輸出到控制檯

	return;					//程序結束
}

這樣寫是不可以的,越界後的值是不可控的,在編寫程序的時候,一定要避免越界!看一下程序的運行結果:
在這裏插入圖片描述

一個緩衝區溢出的程序

通過這個程序,可以瞭解一下所謂的緩衝區溢出,挺有意思的:

#include <stdio.h>			//頭文件
#include <windows.h>		


void Fun()					//定義函數
{
	while(1)				//無限循環
	{
		printf("1匹黑馬,專注於滲透測試與二進制安全!\n");		//輸出內容
	}
}
int check()					//定義函數
{
	int arr[9];				//定義數組,可以存儲9個數
	arr[10] = (int)&Fun;	//把Fun()函數的起始地址轉爲int類型存到數組的第11位中
	return 0;
}
void main()					//程序入口
{	


	check();				//調用函數
	getchar();
	return;					//getchar
}

運行結果:
在這裏插入圖片描述
從堆棧圖中就可以理解這是怎麼回事:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章