程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言學習筆記(十)

C語言學習筆記(十)

編輯:關於C

1變量指針

 

變量的指針就是指向變量的地址,專門用來存放變量地址的變量稱為指針變量。

 

1.1指針變量的定義

 

指針變量是專門用來存放地址的變量,C語言將它定義為指針類型。指針變量也是變量,但指針變量中存放的不是變量的值,而是地址。

 

定義指針變量的一般格式是:

 

類型標示符*指針變量名;

 

例如:

 

int *pa,*pb;

 

float *q;

 

注:1這種語句僅僅是定義了指針變量,並沒有明確的聲明指向某一具體變量。

 

2指針變量前面的“*”代表該變量的類型是指針型的變量,因此它的變量名實pa和pb,而不是*pa、*pb;

 

1.2指針變量的賦值與引用

 

和普通變量一樣,指針變量只有賦值之後才有意義,指針變量中存放的是變量的地址,所以就不允許用戶隨意為其賦常量值,一般情況下,指針變量可以通過取地址運算符和地址賦值運算來賦值。

 

取地址運算符“&”可以加在變量和數組元素前面來取得他們的內存地址,因為指針變量也是變量,所以該運算符也可以加在指針變量前面取值,例如:

 

int n1,n2;

 

int *p1,*p2,*p3;

 

float x,*p4,y;

 

p1=&n1;

 

p2=&n2;

 

p3=p2;

 

又上可知,指針變量的賦值方式是:

 

指針變量名=&變量名;

 

指針變量名=另一個已經賦值的指針變量;

 

指針變量的類型必須保證與其存放的變量類型是一致的,但有一個是例外的,就是C語言中允許出現空指針,也就是值是0的指針,含義是指針無指向,常用來判斷返回指針的函數是否成功的標志。

 

當指針變量指向基本變量以後,就可以利用間接訪問的方法來訪問數據,此時使用取內容運算符“*”來訪問數據,該運算符是通過指針變量來訪問它所指向的變量時使用的運算符,基本格式為:

 

*指針變量

 

一旦將變量的地址賦值給指針變量後,那麼*指針名和變量名是等價的,除非改變指針變量的指向,否則對指針的修改都會影響變量的值。例如:

 

int x,y1,*pi;

 

double d;

 

pi=&x;

 

x=1;

 

/*此時執行下面語句*/

 

y1=*pi+9;

 

實際上等價於:y1=x+9;

 

下面是使用指針變量的例子代碼:

 

 

#include "stdio.h" 

main() { 

     int num=12, *pt;      /*定義一個指向int型數據的指針變量pt */ 

     float pi=3.14, *pf;       /*定義一個指向float型數據的指針變量pf */ 

     char ch='m', *pc;     /*定義一個指向char型數據的指針變量pc */ 

     pt=#               /*取變量num的地址,賦值給pt */ 

     pf=π      /*取變量pi的地址,賦值給pf */ 

     pc=&ch;       /*取變量ch的地址,賦值給pc */ 

     printf("num=%d, *pt=%d\n", num, *pt); 

     printf("pi=%4.2f, *pf=%4.2f\n", pi,*pf); 

     printf("ch=%c, *pc=%c\n", ch, *pc); 

  } 

指針交換:

 

 

#include "stdio.h" 

main(){ 

   int a,b; 

   int *p1,*p2,*p; 

   p1=&a; p2=&b; 

   scanf("%d%d",p1,p2); 

   if (a<b){ 

      p=p1;p1=p2;p2=p; }               /*交換的是地址不是地址裡面的內容*/ 

   printf("the max is %d.\n",*p1);  

內容交換:

 

 

#include "stdio.h" 

main() {  

  int a,b,t; 

   int *p1,*p2; 

   p1=&a; p2=&b; 

   scanf("%d%d",&a,&b); 

   if (a<b){ 

    t=*p1;* p1=*p2;*p2=t;}               /*交換的是地址裡面的內容不是地址*/ 

   printf("the max is %d.\n",*p1);  

2指針變量的運算

 

指針也就是地址,指針變量也可以進行某些運算。

 

2.1&和*運算

 

&是取地址運算符,功能是取變量的地址。

 

*是取值運算符,功能是取指針變量保存的地址所在的內存內容。

 

如:

 

int a;

 

int *p;

 

p=&a;

 

此時*p與a是相同的,表示同一個變量,簡單的講,*和&是互逆的運算。

 

2.2++和--運算

 

在C語言中,指針也可以進行自加和自減運算以及與整數做加減運算。但指針運算與整數運算不同,它與指針所執行的變量大小有關.

 

在指針的應用中,經常會出現指針的加1或減1與*運算符相結合的情況,例如:

 

*p++含義是訪問指針p指向的數據,然後指針變量後移一個元素的位置。

 

*(p++)含義是指針變量後移一個元素的位置,然後訪問元素。

 

假設p指向整型變量a,那麼有以下結論:

 

1(*p)++與a++等價;

 

2*(p++)與*p++都能得到變量a的值,但p已經不再指向a;

 

3*p+1與a+1等價;

 

4(*p)++與*p++是不同的。

 

2.3比較運算符

 

一般情況下,當兩個相同類型的指針變量被正確賦值後,就可以對指針變量進行比較運算。相同類型的指針變量的運算關系包括:>、<、>=、<=、==、!=。例如比較兩個相同類型的指針,如果他們相等,就說明他們指向同一個地址。

 

在比較時,高地址大於低地址。

 

指向不同數據類型的指針之間進行比較關系運算是沒有意義的。但是一個指針可以和NULL(0)做等或不等的關系運算,用來判斷該指針是否為空。

 

2.4減法運算

 

C語言運行兩個類型相同的指針變量進行相減,操作結果是兩個指針之間的元素個數,實際上是兩個指針地址相減之差再除以數據類型的長度。

 

指針運算例子代碼:

 

 

#include "stdio.h" 

main(){ 

  int a=10,b=30,*p1=&a,*p2=&b;   /*定義指針變量,同時給指針變量初始化*/ 

  printf("%d  %d  %d  %d  %x  %x  %x  

          %x\n",a,b,*p1,*p2,p1,p2,&p1,&p2);  /*輸出數據,比較觀察數據之間的聯系*/ 

  a++;(*p2)++;           /*變量和指針指向的變量的自加運算比較*/ 

  printf("%d  %d  %d  %d  %x  %x  %x  

           %x\n",a,b,*p1,*p2,p1,p2,&p1,&p2); 

  *p1++;*p2--;                 /*自加(減)運算與指向運算的優先級比較*/ 

  printf("%d  %d  %d  %d  %x  %x  %x  

           %x\n",a,b,*p1,*p2,p1,p2,&p1,&p2); 

   a=123;*p2=99;b=88;  /*對指針變量的賦值*/ 

   printf("%d  %d  %d  %d  %x  %x  %x  

           %x\n",a,b,*p1,*p2,p1,p2,&p1,&p2); 

  p1++;p2++;    /*地址改變以後,數據值與地址的變化*/ 

   printf("%d  %d  %d  %d  %x  %x  %x  

             %x\n",a,b,*p1,*p2,p1,p2,&p1,&p2); 

   printf("%d  %d\n",p1-p2,p2-p1);  /*指針變量的相減*/ 

 } 

3指針變量作為函數的參數

 

在函數部分我們知道可以使用return語句返回函數值,這種方式只能返回一個數據,但使用指針可以實現對數據的間接訪問,用指針作為函數的參數,返回後就可以修改多個值了。

 

例子:調用函數,計算兩個數相加和相減的值,並在main函數中打印。

 

 

#include "stdio.h" 

void  fun ( int x , int y,int *pa,int *ps ) {               /*兩個數交換,形參為指針*/ 

int add=0 , sub=0 ; 

*pa=x+y ;  

*ps=x–y ;}                                    /*指針內容改變*/ 

main ( ){ 

int a , b , add=0 , sub=0 ; 

scanf ( " %d %d " , &a , &b ) ; 

printf ( " a=%d , b=%d \n " , a , b ) ; 

fun ( a , b,&add,&sub) ; 

printf ( " %d + %d =%d \n " , a , b , add ) ; 

printf ( " %d – %d =%d \n " , a , b , sub ) ;} 

在利用指針作為函數的參數是,要了解在調用函數中如何正確的使用指針變量才可以改變參數的值,例如要交換兩個數據的值,可以由3種方式:

 

3.1以普通變量作為參數完成交換:

 

void swap1(int x,int y){

 

int temp;

 

temp=x,x=y,y=temp;

 

}

 

這種調用僅僅是在函數中將數據交換了,當函數調用結束,返回到主函數中時,形參內存被釋放,實際並沒有交換。

 

3.2以指針變量作為參數實現數據交換:

 

void swap1(int *p1,int *p2){

 

int *p;

 

p=p1,p1=p2;p2=p;

 

}

 

這種交換同樣實現不了功能,調用結束後僅僅是實現了兩個指針指向的交換,而並沒有實現真正的數據交換。

 

3.3交換指針變量所指向的內容:

 

void swap4(int *p1,int *p2){

 

int temp;

 

temp=*p1,*p1=*p2,*p2=temp;

 

}

 

這樣才算實現了真正的數據交換。

 

4指針與一維數組

 

數組是一組相同類型數據的集合,數組中各個元素在內存占據連續的存儲單元,每個內存單元都有相應的地址。數組所在內存單元的首地址稱為數組的指針,數組元素所在內存單元的首地址稱為數組元素的指針,數組指針和數組元素指針是兩個不同的概念。

 

4.1指向一維數組元素的指針

 

不帶方括號的數組名就是該數組的指針,可以把數組名或者第一個元素的地址賦值給指針。例如以下幾個語句是合法的:

 

int a[5],*p,*q;

 

p=a; //保存數組的首地址

 

q=&a[3]; //保存數組中第四個元素的地址

 

由於數組名代表一維數組的首地址,也就是第0個元素的地址,因此以下兩條語句是等價的:

 

p=a;

 

p=&a[0];

 

4.2用指針訪問一維數組元素

 

指針指向數組之後,就在指針和數據之間建立了聯系。可以通過指針訪問數組的各個元素,當然也可以使用下標訪問數組元素,但是使用指針訪問能使程序占用內存更少,運行速度更快。以下代碼借助指針實現了數組元素的輸入和輸出:

 

 

#include "stdio.h" 

main(){ 

  int arr [10], *pa=arr, i;  

  printf("Input 10 numbers: "); 

  for(i=0; i<10; i++) 

    scanf("%d", pa+i);  /*使用指針變量來輸入數組元素的值*/ 

  printf("array[10]: "); 

  for(i=0; i<10; i++) 

   printf("%d  ", *(pa+i)); /*使用指向數組的指針變量輸出數組*/ 

  printf("\n"); 

由於指針是變量,在元素的處理過程中,可以通過對地址的運算,直接得到元素的地址,然後訪問數據元素,上面的代碼也可以寫成:

 

 

#include "stdio.h" 

main(){ 

  int arr [10], *pa=arr;  

  printf("Input 10 numbers: "); 

  for(;pa<arr+10;pa++) 

    scanf("%d", pa);    /*使用指針變量來輸入數組元素的值*/ 

  printf("array[10]: "); 

  pa=arr; 

  for(;pa<arr+10;pa++) 

   printf("%d  ", *pa); /*使用指向數組的指針變量輸出數組*/ 

  printf("\n"); 

這種訪問方式也成為指針法訪問數組中的元素,能夠提高程序質量。在使用指針時應特別注意指針的越界問題,注意指針變量的變化。

 

例子:使用指針變量統計輸入數據中的正數個數。

 

 

#include "stdio.h" 

main() {  

   int  a[10]; 

   int  i,*p,count=0; 

   for(i=0;i<10;i++)  

    scanf("%d",a+i); 

   printf("\n"); 

   for(p=a;p<a+10;p++) {                /*指針可以移動10次*/ 

      if (*p>0) { 

          count ++; 

          printf("%d",*p); 

          if (count % 4==0) printf("\n"); 

      }  

    } 

 

 

摘自 letthinking的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved