C指針與數組學習總結

引言:C語言裏,指針就是它的靈魂,是它能如此高效的原因,同時也是C語言學習的難點;最近在B站看完翁愷老師關於指針和數組的視頻,我感覺醍醐灌頂,很多模糊難辨的細節問題有了自己的理解。這裏想寫下來作爲總結和記錄,水平有限,懇請指正。

  • 一、基本概念總結
    1、C指針(變量的房間號):是一個值爲內存地址的變量。
  • 地址運算符:&,取地址運算
    int a = 1;
    ptr = &a;
  • 地址運算符:*,取值運算符
    b = *ptr;
    注:&和 *爲互逆運算符。
char stuName ,name;//定義字符型變量stuName,name
char *pStu        ;               //定義指向字符型變量的指針變量pStu
char *pNew;//定義指向字符型變量的指針變量pNew
pStu = &stuName;//取變量stuName地址賦值給指針變量pStu
pNew = pStu;//把指針變量pStu賦值該pNew
name = *pNew;//把pNew指向的內存單元的值賦給name

2、數組(存放數據的容器)

  • 所有元素具有相同的數據類型;
  • 一旦創建,不能改變大小;
  • 數組中的元素在內存中是連續依次排列的。

數組元素本身不能被賦值(可以初始化)
如:int ar[] ={1,2,3,4,3,};//引用時下標從零開始,0–n-1;
也可以採用遍歷:

for (i=0; i<length; i++{
	b[i] =a [i];
}

二維數組
int a[3][5]; //l理解爲一個三行五列的矩陣
初始化:

int a[3][5] = {
{0,1,2,3,4},
{2,3,4,5,6},
{4,5,6,7,8},
};

或者遍歷:

for(i=0; i<3;i++){
	for(j=0;j<5;j++){
	a[i][j] = i*j;
	}
}

注:

  • 列數必須給出,行數可由編譯器來數(a[][5]是合法的);
  • 每一個{}由逗號分隔;
  • 最後的逗號可以存在;
  • 如果省略,表示補零;

二、深入理解指針和數組
1、指針與數組本質聯繫
數組中 &a = a = a[0]; 數組的存儲地址由第一個存儲單元a[0]的地址確定,這三個式子意思都一樣,表示a[0]的地址。
所以 :

  a + 2 = = &a[2];
 *(a+2) == &a[2];
 

函數參數表中的數組實際上就是指針;
sizeof(a)== sizeof(int*);
因此,以下四種函數原型是等價的:

int sum(int *ar, int n);
int sum(int *,int );
int sum(int ar[], int n);
int sum(int[],int );

所以:
int int a[10];
int *p = a; //無需&操作

  • 但是數組的單元表達的是變量,需要用&取地址:
    a == &a[0];
  • []運算符可以對數組做,也可以對指針做:
    p[0] 等價於a[0];
  • *運算符可以對指針做,也可以對數組做:
    *a = 25;
  • 數組變量是const的指針,所以不能被賦值:
    int a[] 等價於 int *const a;

2、指針與const
(1)指針是const:表示一旦得到了某個變量的地址,不能再指向其他變量:

int *const q = &i;//q是const
*q = 26;//OK
q++//ERROR
//可以這麼理解:指針本身是隻讀的const不能變,而它指向的變量可以變

(2)所指是const:表示不能通過這個指針去修改那個變量:

const int *p = &i;
*p = 26;//ERROR
i = 26;//OK
p = &j;//OK
//可以認爲*p是const,但指針本身可以變,變量i本身可以變

總結:判斷哪個被const了的標誌是const在*前還是後面
const * --所指的東西不能被修改
*const–指針不能被改變。

三、指針作爲函數參數的巧妙用途
作爲函數的參數:
void f(int *p);
在被調用時得到了某個變量的地址:
int i = 0;
f(&i);//該函數可以通過指針訪問
具體應用場景:

  • 函數返回多個值,某些值只能通過指針返回;
  • 傳入參數實際是需要保存帶回的結果的變量;
  • 函數返回運算的狀態,結果通過指針返回;
  • 常用套路是讓函數返回特殊的不屬於有效範圍內的值表示出錯:-1或0;

以下是實踐函數:

/* 指針練習1,指針概念的辨析 */ 
#include<stdio.h>

void f(int *p);       //函數原型,void表示函數沒有返回值,如果是()內的void表示函數不帶參數
void g(int k);        //用來對照指針變量的 

int main(void){
	int i = 6;
	printf("&i = %p\n",&i);  //%p是以十六位的指針地址形式輸出 
	f(&i);       //由於函數參數爲指針變量,調用時&i爲取變量i的地址
	g(i); 
	return 0;
	 
} 

void f(int *p){
	printf("p = %p\n",p);
	printf("*p = %d\n",*p);     //*p爲取指針所指向地址的值,即取值
	*p = 26 ;   //改變*p的值,看i本身變不變==實際上i會變,因爲*p作爲一個整體代表了i,可以把它看成一個int變量 
}

void g(int k){
	printf("k = %d\n",k);
} 
/* 指針練習2,指針一些具體的使用 */
#include<stdio.h>

void swap(int *pa,int *pb);

int main(void)
{
	int a = 5;
	int b = 6;
	swap(&a,&b);
	printf("a = %d,b = %d",a,b); 
	return 0; 
 } 
 
 void swap(int *pa,int *pb)   //使用指針來操作交換函數swap() 
 {
 	int t = *pa;
 	*pa = *pb;
 	*pb = t;
 }
/* 指針練習3 ,用一個函數找出數組中最大數和最小數 */
#include<stdio.h>

void minmax(int a[], int len, int *max, int *min );

int main(void)
{
	int a[] = {1,2,9,10,45,70,1,76,87,8,};
	int min, max;
	minmax(a, sizeof(a)/sizeof(a[0]), &max, &min);
	printf("min = %d,max = %d",min,max);
	
	return 0;
	
}

/*函數返回多個值時,某些值只能通過指針返回(其實該函數並沒有返回值, 
但是通過指針的特性,直接找到所要操作變量的地址,然後改變裏面的值,這裏可以類比爲返回值*/
//傳入的參數實際上是需要保存的帶結果的變量 

void minmax( int a[], int len, int *max, int *min)
{
	int i;
	*max = *min = a[0];
	for( i=0; i<len; i++ ){
		if(a[i]<*min){
			*min = a[i];
		}
		if(a[i]>*max){
			*max = a[i];
		}
		
	}
	
	
}

到此結尾了,我這裏的多爲筆記總結,要深入理解還是要自己敲幾行試試。

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