日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

C语言:随笔5--指针1

發(fā)布時(shí)間:2023/11/27 生活经验 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言:随笔5--指针1 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

指針雖然是一個(gè)重要的概念,但是一點(diǎn)也不復(fù)雜。但他的確是C語(yǔ)言的精華。

正確而靈活的運(yùn)用它,可以有效的表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu);能動(dòng)態(tài)的分配內(nèi)存;能方便的使用字符串,有效而方便的使用數(shù)組。

為了說(shuō)清楚什么是指針,必須弄清楚數(shù)據(jù)在內(nèi)存中是如何存儲(chǔ)的,又是如何讀取的。

那就從一個(gè)美麗的故事開(kāi)始吧。。。。

比如,昨天小A去圖書(shū)館借一本“我是美女”這本書(shū)的時(shí)候,在路上不小心碰到了一個(gè)帥哥,然后小A就非常勇敢的沖了上去一把掏出手機(jī),文了該帥哥加的電話號(hào)碼和地址,然后帥哥覺(jué)得小A實(shí)在長(zhǎng)相一般不肯告訴他家的電話號(hào)碼,就只是說(shuō)了他家的地址,他是住在單身公寓的102號(hào)房,那這樣小A就可以去找他了哈哈,因?yàn)樾已經(jīng)知道了他家的地址了,那這就跟我們的內(nèi)存掛鉤了,我們知道內(nèi)存有兩個(gè)屬性,第一個(gè)內(nèi)存是一個(gè)線性的存儲(chǔ)空間,有兩個(gè)屬性一個(gè)是地址,另一個(gè)是地址上邊存放的數(shù)據(jù)。OK,內(nèi)存是用來(lái)存放數(shù)據(jù)的,就像我們的地址,每一個(gè)門(mén)牌號(hào)碼都有一個(gè)家,家里面就會(huì)放帥哥,就是一樣的道理。我們通過(guò)地址才能夠索引到某個(gè)我們要索引的內(nèi)存,如果我們不知道他們的地址門(mén)牌號(hào)我們應(yīng)該怎么找呢,不能一個(gè)個(gè)挨家敲門(mén)吧。所以,我們的內(nèi)存都是有編好地址的,所以只要在固定的地址里面它會(huì)有對(duì)應(yīng)的數(shù)據(jù)。我們存數(shù)據(jù)就是靠這個(gè)地址來(lái)索引的,那我就知道我的東西存在哪里了,也知道我的東西要去哪里拿。

內(nèi)存區(qū)的每一個(gè)字節(jié)都有一個(gè)編號(hào),這就是“地址”。如果在程序中定義了一個(gè)變量,在對(duì)程序進(jìn)行編譯時(shí),系統(tǒng)就會(huì)自動(dòng)的給這個(gè)變量分配內(nèi)存單元。這叫做局部變量。

在C語(yǔ)言中,對(duì)變量的訪問(wèn)有兩種方式,直接訪問(wèn)和間接訪問(wèn)。

舉個(gè)例子就是:

為了開(kāi)一個(gè)A抽屜,有兩種方法:

(1)一種方法是將A鑰匙帶在身上,需要時(shí)直接找出該鑰匙打開(kāi)抽屜,取出所需的東西。-----直接訪問(wèn)

直接訪問(wèn)如:a=5;

系統(tǒng)在編譯時(shí),已經(jīng)對(duì)變量分配了地址,例如若變量a分配的地址是2000,則該語(yǔ)句的作用就是把常數(shù)5保存到地址為2000的單元。(我們說(shuō)內(nèi)存中有兩個(gè)屬性嘛,一個(gè)是地址,然后和地址對(duì)應(yīng)的空間存放的一個(gè)數(shù)據(jù),那他地址就是2000存放的數(shù)據(jù)就是5,這個(gè)變量呢我們稱之為a。)

(2)另外一種方法是:為安全起見(jiàn),將A鑰匙放到另外一個(gè)抽屜B中鎖起來(lái)。如果需要打開(kāi)A抽屜,就需要先找出B鑰匙,打開(kāi)B抽屜,取出A鑰匙,再打開(kāi)A抽屜,取出A抽屜中之物。-----間接訪問(wèn)

間接訪問(wèn)如:scanf("%d",&a);//這個(gè)函數(shù)的作用讀取一個(gè)整形的變量,把他的值賦值給a

當(dāng)我們調(diào)用這個(gè)函數(shù)的時(shí)候,把變量a的地址傳遞給函數(shù)scanf,函數(shù)首先把該地址保存到一個(gè)單元中,然后把從鍵盤(pán)接收的數(shù)據(jù)通過(guò)所存儲(chǔ)的地址保存到變量a中。

1、初識(shí)指針

在C語(yǔ)言中指針是一種特殊的變量,它存放的是地址(一般變量存放的是值嘛,例如剛才a=5,變量a存放的是5;但是我們的指針?biāo)且粋€(gè)特殊的變量它是存放地址的,叫做指針變量)。假設(shè)我們定義了一個(gè)指針變量,int *i_pointer用來(lái)存放整型變量i的地址。可以通過(guò)語(yǔ)句i_pointer=&i;(取得i的地址把他賦值給i_pointer這個(gè)指針變量)

如上圖:假設(shè)變量i,變量j,變量k他們的地址分別是2000,2002,2004;它里邊存放的數(shù)據(jù)分別為3、6、9;而我們定義的這個(gè)指針變量呢它里邊存放的是一個(gè)地址,我們這里通過(guò)這一句i_pointer=&i,使得變量i的地址存放到了B處,所以B處存放的是i的地址,指針變量也是變量,數(shù)組變量也是變量,它跟變量是一樣的道理,只是指針變量存放的是一個(gè)地址,而我們普通變量存放的是一個(gè)值。我們只需要把他靈活的應(yīng)用就很NB了。

將i的地址(2000)存放到i_point中。這時(shí),i_pointer的值就是(2000)即變量i所占用單元的起始地址。(因?yàn)椴煌?lèi)型在內(nèi)存中占的字節(jié)數(shù)是不同的)

要存取變量i的值,可以采用間接方式:先找到存放“i的地址”的變量i_pointer,從中取出i的地址(2000),然后取出i的值3。見(jiàn)下圖:直接的話,直接i=3;就取出來(lái)了。

*:叫做取值操作符;

&:叫做取地址操作符;(后邊會(huì)詳細(xì)分析這兩個(gè)操作負(fù)要怎么用,目前只是基本使用方法)

int i=2000;//i的值為2000
int *pointer;//我們聲明一個(gè)指針pointer//此處的*號(hào)并不是取值操作符,這個(gè)是申明它為指針的一個(gè)特征
pointer=&i;//在這里取出i的地址,比如說(shuō)他的地址是1000,就把他的地址給了變量pointer//這個(gè)是取址
printf("%d\n",*pointer)//那我通過(guò)這個(gè)*號(hào),取出指向這個(gè)地址的里邊的值,也就是打印出來(lái)的值應(yīng)該是2000//這個(gè)才是取值操作

知道了一個(gè)變量的地址,就可以通過(guò)這個(gè)地址來(lái)訪問(wèn)這個(gè)變量,因此又把變量的地址稱為該變量的”指針“。指針指向的是一個(gè)地址。而指針變量呢,C語(yǔ)言中定義一類(lèi)特殊的變量這些變量專門(mén)用來(lái)存放變量的地址,稱為指針變量。(所以地址和變量是完全不同的兩回事。)

注意:指針變量的值(即指針變量中存放的值是地址(即指針))要區(qū)分“指針(是一個(gè)地址)”和“指針變量(是一個(gè)變量)”這兩個(gè)概念。

//定義一個(gè)指針變量
float *pointer_3;//pointer_3是指向float型變量的指針變量//pomiter_3是變量名而不是*pointer_3//*號(hào)只是起到表明它是指針
//*表示定義,*可以表示聲明定義一個(gè)指針,如果不在聲明的情況下,它是取值操作符

//下邊可以使用賦值語(yǔ)句使一個(gè)指針變量得到另一個(gè)變量的地址,從而使他指向一個(gè)該變量。如:

首先我們的pointer_1里面存放的是i的地址,所以它指向的是i這個(gè)變量;pointer_2存放的是j的地址,所以指向的是j這個(gè)變量。那么如果有如下語(yǔ)句:

pointer_1=pointer_2;//就是將pointer_2這個(gè)變量里面的內(nèi)容把他存放覆蓋了pointer_1這個(gè)里面的內(nèi)容。所以此時(shí)pointer_1里邊存放的不再是i的地址了,而是j的地址了。而此時(shí)pointer_1指向了j。當(dāng)然pointer_2沒(méi)有發(fā)生改變還是指向的j;也就是說(shuō)現(xiàn)在i被人拋棄了而兩個(gè)都直奔j了。

指針變量的前面的*號(hào)表示改變量的類(lèi)型是指針變量。即類(lèi)型說(shuō)明符 *變量名;

在定義指針變量時(shí),必須指定基類(lèi)型。特別注意的是:只有整型變量的地址才能放到指向整型變量的指針變量中。

請(qǐng)牢記,指針變量中只能存放地址(指針),不要將一個(gè)整數(shù)(或任何其他非地址類(lèi)型的數(shù)據(jù))賦給一個(gè)指針變量,否則編譯器也會(huì)把該值當(dāng)成一個(gè)地址來(lái)處理。

&變量名;//地址運(yùn)算符&來(lái)表示變量的地址。

2、指針做函數(shù)參數(shù)

輸入a,b兩個(gè)整數(shù),按大小順序輸出

#include<stdio.h>
//交換a,b的值
void swap(int *p1,int *p2);//行參定義的指向整數(shù)型的指針變量void main()
{int a,b;int *pointer_1, *pointer_2;scanf("%d %d",&a,&b);pointer_1=&a;//pointer_1該指針變量指向的是a。pointer_2=&b;if(a<b){swap(pointer_1,pointer_2);//所以實(shí)參需要傳入的是????指針呢?還是指針變量。pointer_1叫做指針變量}printf("\n%d > %d\n",a,b);    
}
void swap(int *p1,int *p2)
{int temp;printf("I'm swap....\n");temp=*p1;*p1=*p2;*p2=temp;
}

輸入a,b,c三個(gè)整數(shù),按大小順序輸出

#include<stdio.h>
//交換a,b的值
void exchange(int *q1,int *q2,int q3);//使得a>b>c。void main()
{int a,b,c;int *p1, *p2,*p3;scanf("%d %d %d",&a,&b,&c);p1=&a;//p1指針指向a的地址p2=&b;p3=&c;exchange(p1,p2,p3);//與上邊定義相比,是做了int *q1=p1;這個(gè)操作。(行參和實(shí)參的一個(gè)交換就相當(dāng)于一個(gè)賦值操作,他們是通過(guò)棧來(lái)完成的)printf("%d %d %d\n",a,b,c);    
}
void exchange(int *q1,int *q2,int *q3)
{void swap(int *pt1,int *pt2);//用于交換if(*q1<*q2)//p1和q1都是指向a變量的//即如果a<b的話交換{ swap(q1,q2);}if(*q1<*q3)//a如果小于c的話c,交換{ swap(q1,q3);}if(*q2<*q3)//b如果小于c的話再交換{ swap(q2,q3);}}
void swap(int *pt1,int *pt2)
{int temp;temp=*pt1;*pt1=*pt2;*pt2=temp;
}

3、數(shù)組與指針

(因?yàn)閿?shù)組和指針都是指向了一個(gè)地址,數(shù)組是比較穩(wěn)定的,而指針是隨時(shí)可變的;數(shù)組在定義的時(shí)候就占用了空間,而指針是一個(gè)變量,指針的空間隨時(shí)可以消除,而數(shù)組不能)

一個(gè)變量有地址,一個(gè)數(shù)組包含若干元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲(chǔ)單元(而且他們是連續(xù)的),他們都有相應(yīng)的地址。

指針變量(里邊存放的是變量的地址)既然可以指向變量,當(dāng)然也可以指向數(shù)組元素(把某一元素的地址放到一個(gè)指針變量中)

所謂數(shù)組元素的指針就是數(shù)組元素的地址。

定義一個(gè)指向數(shù)組元素的指針變量的方法,與以前介紹的指向變量的指針變量相同。

int a[10];//定義a為包含10個(gè)整型數(shù)據(jù)的數(shù)組
int *p;//定義p為指向整型變量的指針變量 
//應(yīng)當(dāng)注意,如果數(shù)組為int型,則指針變量的基類(lèi)型也應(yīng)為int型
p=&a[2];//指針指向數(shù)組的第三個(gè)元素;把a(bǔ)[2]元素的地址賦給指針變量p,也就是說(shuō)把p指向a數(shù)組的第2號(hào)元素。
p++;//表示

引用數(shù)組元素,可以用下標(biāo)法也可以用指針?lè)?#xff1a;

(1)下標(biāo)法:a[i]的形式;

(2)指針?lè)?#xff1a;*(a+1)或者*(p+i);//因?yàn)閍是第一個(gè)元素的地址,其中的加i就是指向的是第i個(gè)元素,不是說(shuō)地址加i,因?yàn)橐词裁搭?lèi)型。

其中a是數(shù)組名,p是指向數(shù)組元素的指針變量,其初值p=a即p=&a[0];

注意:數(shù)組名(在編譯器是編譯為一個(gè)地址的)即“編譯成數(shù)組的第一個(gè)元素的地址。”(這就是上邊說(shuō)的相似的地方)

用數(shù)組名做函數(shù)的參數(shù)--------

如:

void f(int arr[],int n)
{......
}
void main()
{int arr[10];... ...f(arr,10);//數(shù)組名相當(dāng)于該數(shù)組的首地址
}

上述中的,f(int arr[],int n),在編譯時(shí)是將arr按照指針變量處理的,相當(dāng)于將函數(shù)f的首部寫(xiě)成f(int *arr,int n)所以以上這兩種寫(xiě)法是等價(jià)的。

需要說(shuō)明的是:C語(yǔ)言調(diào)用函數(shù)時(shí)虛實(shí)結(jié)合的方法,都是采用值傳遞方式,當(dāng)用變量名作為函數(shù)參數(shù)時(shí),傳遞的是變量的值;當(dāng)用數(shù)組名作為函數(shù)參數(shù)時(shí),由于數(shù)組名代表的是數(shù)組首元素地址,因此傳遞的值是地址,所以要求形參為指針變量。

例子:將數(shù)組a中n個(gè)整數(shù)按相反順序存放。

#include<stdio.h>
void reverse(int x[],int n)//形參x是數(shù)組名
void main()
{int i, a[10]={3,5,7,8,1,0,2,6,9,4};printf(" The original array:\n");for(i=0,i<10,i++){printf("%d",a[i]);}printf("\n");reverse(a,10);printf("The Array has been inverted:\n");
}
void reverse(int x[],int n)
{int temp,i,j,m;m=(n-1)/2;for(i=0;i<=m;i++){j=n-1-i;temp=x[i];x[i]=x[j];x[j]=temp;}
}

改變一下用指針做函數(shù)的參數(shù):

#include<stdio.h>
void reverse(int *x,int n)//形參x為指針變量
void main()
{int i, a[10]={3,5,7,8,1,0,2,6,9,4};printf(" The original array:\n");for(i=0,i<10,i++){printf("%d",a[i]);}printf("\n");reverse(a,10);printf("The Array has been inverted:\n");
}
void reverse(int *x,int n)//形參x為指針變量
{int *p,temp,*i,*j,m;m=(n-1)/2;//中間序號(hào)i=x;//前邊的序號(hào)//i指向數(shù)組的第一個(gè)元素j=x-1+n;//后邊的序號(hào)//j指向數(shù)組的最后一個(gè)元素p=x+m;//指向中間配對(duì)for(;i<=p;i++,j--){temp=*i;*i=*j;*j=temp;}
}

用指針做參數(shù)------

例子:從10個(gè)數(shù)中找出最大值和最小值。

#include<stdio.h>
int max,min;//全局變量
void max_min_values(int array[],int n);
void main()
{int i,number[10];printf("Enter 10 integer numbers:\n");for(i=0;i<10;i++){scanf("%d",&number[i]);}max_min_values(number,10);printf("\nmax=%d,min=%d\n,"max,min);
}
void max_min_values(int array[],int n)
{int *p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;p<array_end;p++){if(*p>max){max=*p;}else if(*p<min){min=*p;}}}

總結(jié):如果有一個(gè)數(shù)組,想在函數(shù)中(子程序)改變此數(shù)組中的元素值,實(shí)參與形參的對(duì)應(yīng)關(guān)系有以下四種:

(1)形參和實(shí)參都用數(shù)組名:

void main()
{int a[10];f(a,10)
}
void f(int [],int n)
{......
}

(2)實(shí)參采用數(shù)組名,形參用指針變量。如:

void main()
{int a[10];f(a,10);
}
void f(int *a,int n)
{......
}

(3)實(shí)參和行參都用指針變量。如:

void main()
{int a[10];int *p=a;//指針變量p指向數(shù)組的首地址f(p,10);//傳指針相當(dāng)于傳a數(shù)組的地址
}
void f(int *x,int n)//int *x指針相當(dāng)于指向a的地址,相當(dāng)于傳值的時(shí)侯x=p,p指向a那么x也指向a
{......
}

(4)實(shí)參為指針變量,行參為數(shù)組名。如:

void main()
{int a[10];int *p=a;f(p,10);//1這里把數(shù)組的首地址當(dāng)作實(shí)參傳過(guò)去,
}
void f(int x[],int n)//2定義數(shù)組來(lái)接收首地址,說(shuō)明位置起始點(diǎn)一樣指向了同一組數(shù)組。
{......
}

例子:對(duì)一個(gè)數(shù)組中的元素按照從大到小的順序排列一下。

#include<stdio.h>
int max,min;//全局變量
void sort(int array[],int n);
void main()
{int *p,i,a[10]={3,7,4,9,2,0,5,8,1,6};printf("The origial array:\n");for(i=0;i<10;i++){  printf("%d",a[i]);}printf("\n");p=a;sort(p,10);printf("The result is:\n");for(p=a;i=0;i<10;i++){printf("%d",*p);p++;}printf("\n");
}
void sort(int x[],int n)
{int i,j,k,t;for(i=0;i<n-1;i++){k=i;//假設(shè)第一個(gè)是最大的,如果接著的那個(gè)比他大那就把他調(diào)過(guò)來(lái)for(j=i+1;j<n;j++){if(x[j]>x[k]){t=x[j];x[j]=x[k];x[k]=t;}}}}

?

總結(jié)

以上是生活随笔為你收集整理的C语言:随笔5--指针1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。