C語言數組與指針,拒絕入坑

前言:寫東西一樣要保存,ctrl s常按着,寫了一晚上,第二天全沒了,快要哭了。要不是自己在指針這裏浪費了很多時間,我可能就不會重新寫了,希望大家能看懂學會,別再走彎路了。

1.內存四區 。

a) 代碼區。代碼。
b)全局區。 全局的常量字符串常量,“abc"變量 。
c)棧區。系統自動開闢,系統自動釋放。並不是很大。
d)堆區。動態開闢的內存,手動開闢,手動釋放。大。

如這個i,上面for循環用了下面還能用,因爲上面用的時候自動開闢,用完就直接釋放了。

#include <stdio.h>
int main() {
	for (int i = 0; i < 8; i++)
		printf("%d", i);
}

2.地址:

把內存以單個字節爲單位,分開。對每一個字節編號,這個編號就是地址。
如同賓館,地址就是房間號
a)編號是連續的。
b) 唯一的。
c) 取地址運算符: &單目運算符優先級() [ ] . 結合性右往左。
在這裏插入圖片描述

	int a;//定義一個整數a
	&a;//&是取地址符,&a返回的是a的地址

3. 首地址

一段內存空間中第一個存儲單元的地址。
存儲單元
如整數 a,他佔四個字節,他的儲存單元就是字節,首地址就是第一個字節的地址
在這裏插入圖片描述
如一維數組a[5],他由五個整數組成,儲存單元就是整數,首地址就是第一個數a[0]的地址,雖然a[0]有四個字節,並且a[0]的地址就是a[0]的第一個字節的地址,但他的存儲單元就是第一個數a[1]。
在這裏插入圖片描述
現在是二維數組 a[ 2 ][ 2] ,它是由兩個一維數組組成,儲存單元是一維數組,首地址就是第一個一維數組的地址,也就是第一個一維數組第一個元素的地址。
在這裏插入圖片描述

寫了整整一晚上,Chrome突然自己關閉了,打開之後全都沒了。(欲哭無淚)
指針的變量定義、指針變量的賦值、指針變量的引用還有一些基礎的就不重新寫了,相信這些很多人都明白(不明白的看這裏C語言指針變量–圖示易懂),下面主要寫大家都比較懵逼的****數組與指針
。(重新寫,真的很蛋疼)

指針變量的加減

指針之間只有加減,而且不是指針和指針的加減,而是指針加減一些字節數

數組與指針

敲黑板

想要理解數組與指針,這兩個概念是必須要好好弄明白的。

首地址:一段內存空間中第- -個存儲單元的地址。存儲單元。
指針變量的加減,以指針所指向的類型空間爲單位進行偏移。

一維數組與指針

1.定義一個一維數組

數組名是這個數組的《首地址》
int a[5];
a指向a[0], a[0] 是int類型 的元素,a的類型就是 int *
&a這個地址指向整個數組,&a的類型int(*)[5];

下面可以看到,a和&a[0]是一樣的,印證了a指向a[0]
a+1比a多四個字節。

	int a[5] = {1,2,3,4,5};
	printf("a:%d \n", a);
	printf("a+1:%d \n", a+1);
	printf("a[0]:%d \n", a[0]);
	printf("&a[0]:%d \n", &a[0]);

a:1898984
a+1:1898988
a[0]:1
&a[0]:1898984

2.訪問數組元素

下標法

int a[5] = {1,2,3,4,5};
for(int i=0;i<5;i++){
printf("%d”, a[i]);
}
12345

指針法

#include <stdio.h>
int main() {
	int a[5] = {1,2,3,4,5};
	int* p = a; //p指向a[0]
	for (int i = 0; i < 5; i++) {
		printf("%d ", *(p + i));    //12345
		printf("%d ", *p++);   		//12345  
		printf("%d ", * (a + i));   //12345
		// printf("%d ", * a ++ );
	}
}
*p : a[0]    	 * (p + 1): a[1]	    *(p + 2): a[2]  這裏的p是沒有變的
P++ 		的p是會變

*(p + i) 加括號是因爲單目運算符比雙目的高,*和++都是單目
單目運算符是指運算所需變量爲一個的運算符,雙目就是兩個。
不能 *a++運算,這樣不合法
在這裏插入圖片描述

二維數組與指針

int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};

數組名: a
a是數組名,也是這個二維數組的首地址
a指向二維數組的第一個存儲單元a[0][ ]。

a[2][3][4] 由 2個維數組 3個一維數組 4個int的元素組成,他的存儲單元就是二維數組,a指向a[0][0]

注意,不管是多少維的,儲存他的地址都是這樣按條排列的,而不會是那種方形的。
在這裏插入圖片描述

概念區分

a,a[0],a[0][0]的地址

a指向a[0],a[0]指向a[0][0],a[0][0]的地址是其第一個字節的地址

int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};
	printf("&a %d\n", &a);
	printf("&a[0] %d\n", &a[0]);
	printf("&a[0][0] %d\n", &a[0][0]);
	
20183524
20183524
20183524

可以看下上下兩個代碼,a是二維數組a[3][4]的數組名也是其首地址,a[0]是一維數組的數組名也是其首地址,所以a和&a是一樣的 a[0]和&a[0]是一樣的,但是a[0][0]是一個數值,是具體的數,&a[0][0]纔是a[0][0]的地址

a和a+1

a指向a[0]這個一維數組。a的類型是: int(*)[4]; a+1 a的第0行 a+1第一行,a+2第二行 所以上面a+1比a的地址多16個字節(4*4)
a[0]指向a[0][0] , a[0]的類型是 intint * , a[0]+1比a[0]多四個字節

	int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};
	printf("a: %d\n", a);
	printf("a+1: %d\n", a + 1);
	********************************
	printf("a[0] %d\n", a[0]);
	printf("a[0]+1 %d\n", a[0] + 1);

a: 	 20183524
a+1: 20183540

a[0]   20183524
a[0]+1 20183528

&a和&a+1

&a+1比&a多了48個字節124(12*4),這是因爲 &a是指整個二維數組a int[3][4]類型是int * [3][4]
&a[0]+1比 &a[0]多16個字節44(4*4),這是因爲 &a[0]指向整個一維數組a[0], int[4]類型是int *[4]

	int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};
	printf("&a: %d\n", &a);
	printf("&a+1: %d\n\n", &a+1);
	*********************************
	printf("&a[0] %d\n", &a[0]);
	printf("&a[0]+1 %d\n", &a[0]+1);

&a:     20379712
&a+1:   20379760

&a[0]   20379712
&a[0]+1 20379728

aa+1(a+1)*a 和*a+1和*(a+1)

  • a,*a和&a都是一樣的,是這個二維數組的地址。
  • **a是取出 *a這個地址存放的數據,也就是a[0][0],也就是1。
  • *a+1:是a的地址加四個字節,相當於a[0][1]。
  • (a+1):先看a+1,a的類型是 int * [4],上面也說了,a+1比a多16個字節(4 * 4),所以地址多16,也就成了下一個一維數組的首地址a[1]的地址,改地址存的數是a[1]的第一個數a[1][0]是5,(a+1)取地址存的數,是5
int a[3][4] = {1,8,7,9,5,6,7,8,9,10,11,12};
	printf("*a: %d\n", *a);
	printf("**a: %d\n", **a);
	printf("*a+1: %d\n", *a+1);
	printf(" *(*a+1): %d\n", *(*a+1));
	printf("*(a+1): %d\n", *(a+1));
	printf(" *(*(a+1)): %d\n", *(*(a+1)));
	
*a:			19921108
**a:		1
*a+1: 		19921112
*(*a+1): 	8
*(a+1):	 	19921124
*(*(a+1)):  5

查找m行n列的元素

下標:a[m][n]
行地址:*(a[m]+n)
數組名: *( *(a+m)+n)

int a[3][4];
a	int(*) [4]
&a 	int(*)[3][4]
a[0]	int*
a[0][0]	int

查找a的第二行第三列的元素

int a[3][4] = {1,8,7,9,5,6,7,8,9,10,11,12};
	printf("(2,3) %d\n\n", *(a[1]+2));
	printf("(2,3): %d\n\n", *(*(a+1)+2));23: 723: 7

多維指針

多維指針和二維指針是一樣的,還是先明白這兩條
首地址:一段內存空間中第一個(也就是最大的那個)存儲單元的地址。存儲單元。
指針變量的加減,以指針所指向的類型空間爲單位進行偏移。

如五維指針a[2][3][4][5][6]
從高往低去拆
其存儲單元爲四維指針

&a ——> 就是一個指向八位數組的指針
a>int()[.][.][.][.]a ——>指向一個四維數組,地址爲* 類型爲 int(*)[. ][. ][.][. ]
a[0]>a[.][.][.]int()[.][.][.]a[0]——> 指向三維數組, a[.][.][.] ,類型爲 int(*)[. ][. ][ .]
a[0][0]>a[.][.]int()[.][.]a[0][0] ——>指向二維數組a[.][ .],類型爲int(*)[ .][ .]
a[0][0][0]>a[.]int()[.]a[0][0][0]——>指向一維數組a[.],類型int(*) [.]
a[0][0]0][0]>,inta[0][0]0][0] ——>指向一個數,地址,類型爲int*
a[0][0]0][0][0]>inta[0][0]0][0][0] ——>就是一個數,類型爲int

ok 今天先寫這些,剩下的儘量明天寫吧,當然還指針有很多很多:

  • 指針數組: int*[ ]
  • 數組指針: int(*)[ ]
  • 函數指針:
  • 指針形參的函數:
  • 結構體指針:
  • 字符串與指針:
  • 指向指針的指針:

參考與B站真的很清晰透徹 C語言Plus

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