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

C語言指針

編輯:關於C
指針變量是包含內存地址的變量,它指向內存中的一塊區域,通過指針的值,可以間接訪問到相應的內存單元的數據,並做相應的修改。   1、指針的定義和簡單使用   定義一個指針變量和定義一般的變量類似,只需在變量名前面加一個“*”。對一個指針變量賦值可以用取地址符&來獲取到一個變量的地址,如果要獲得指針指向的內存區域的數據,用解參考運算符*(也稱為間接運算符,它返回其操作數指向的對象的值)。指針的值為NULL(NULL是stdio.h中定義的符號變量,實際上是0)說明其不指向任何的內存單元,0是唯一直接可以賦值給指針變量的整數值。實際上,*和&是互補的,當兩個運算符連續應用於一個指針變量時,無論順序如何,運算結果相同。同時可以用printf中的格式化字符串%p來輸出指針變量的值,下面是一個簡單的程序。   [cpp]   #include <stdio.h>   int main()   {       int a;       a=9;       //定義並初始化一個指針,命名就可以看出       int *aPtr=NULL;       //將指針指向變量a       aPtr=&a;       printf("The address of a is %p"           "\nThe value of aPtr is %p",&a,aPtr);       printf("\n\nThe value of a is %d"           "\nThe value of *aPtr is %d",a,*aPtr);       printf("\n\nShowing that * and & are complements of "           "each other\n&*aPtr = %p"           "\n*&aPtr = %p\n",&*aPtr,*&aPtr);              return 0;   }         2、用指針做函數的參數   2.1 通過指針實現的引用傳遞   程序設計語言的參數傳遞方式,大致分兩種:值傳遞和引用傳遞。C語言中沒有引用傳遞,但是C語言通過指針間接實現了引用傳遞。通過用指針變量作為函數的參數,可以傳遞變量的地址(只需要在變量前面加上&運算符就可以),這樣,用該地址就可以訪問到主調函數中的該變量的內存地址,並可以進行相應的修改。這樣,在函數執行完畢之後,修改仍然可以得到保留。   2.2 const   const限定符可以告訴編譯器特定的變量的值是不能被修改的。如果想確保函數不會修改傳遞進來的參數值,應該將參數聲明為const。這樣對於C語言中用指針實現的引用傳遞,有四種情況:指向非常量數據的非常量指針(int *aPtr),指向非常量數據的常量指針(int *const aPtr),指向常量數據的非常量指針(const int *aPtr)和指向常量數據的常量指針(const int * const aPtr)。簡單的說,就是指針變量自身和指針指向的變量都有可能是const,這樣就產生了四種情況,這四種情況提供了四種不同的訪問權限,下面分別解釋。   指向非常量數據的非常量指針(int *aPtr):指針的值本身和指針指向變量的值都可以在函數中被修改。   指向非常量數據的常量指針(int *const aPtr):指針的值不能被修改,但是指針指向的變量的值可以被修改。   指向常量數據的非常量指針(const int *aPtr):指針指向的值不能被修改,但是指針本身的值可以被修改。   指向常量數據的常量指針(const int * const aPtr):指針本身和指針指向變量的值都不能被修改。 3、sizeof和指針運算   3.1 sizeof   sizeof是C語言中特殊的一元運算符,可以應用在變量名稱、數據類型和常量之前,它在程序編譯期間以字節為單位來確定數組或其他數據類型的大小。當應用於數組時,sizeof返回數組中的字節總數。如float a[20],sizeof(a)的值應該是4*20,80。當然,如果想獲得數組的大小可以采用sizeof(a)/sizeof(float)。   3.2 指針運算   實際上,指針變量可以進行的算術操作是有限的:遞增,遞減,將指針和整數相加,從指針中減去一個整數或者一個指針減去另一個指針。需要注意的是,對於指針的算術運算,其單位長度並不是一般意義上的1,而是sizeof(TYPE)。這樣,如果float a[14]; float *aPtr=a;(或者int *aPtr=&a[0]); aPtr++;這樣aPtr應該指向的是數組a的第二個元素,也就是a[1],這裡的單位長度就是sizeof(float)。同樣地,如果aPtr=aPtr+5;,這樣aPtr又指向了數組a的第6個元素。如果aPtr-a,這樣可以得到兩個指針之間的元素間隔個數。應該是6。   進行指針運算要注意:   (1)如果將一個指針的值賦給另外一個指針,那麼這兩個指針的類型必須相同,否則應該用類型轉換運算符進行類型轉換。但是,有一個例外就是指向void類型的指針,它是通用指針,可以代表任何指針類型。因此,所有指針類型都可以賦值給void指針,而void指針也可以賦值給任何類型的指針,而不需要任何類型轉換運算符。但是,void指針不能解參考,編譯器知道指向int類型的指針引用的是32位計算機上的4個字節內存,但指向void的指針僅包含未知數據類型的內存位置,也就是說,編譯器不知道指針所引用的字節數。編譯器必須知道數據類型,才能確定所引用的字節數。   (2)除非兩個指針變量都指向的是一個數組中的元素,否則對它們相減的結果沒有任何意義,因為我們不能假設兩個變量在內存中是連續的。   4、指針和數組   4.1 數組和指針的共性   實際上,數組名稱的本質是一個常量指針。因此,int a[6]; int *aPtr;定義一個數組和指針之後,通過a[3],*(a+3)和*(aPtr+3)都可以訪問到數組的第四個元素的值。但是區別在於,aPtr=aPtr+3;這樣aPtr就指向了a數組的第四個元素,但是,不能a=a+3;,因為a是一個數組名,它是一個常量指針它的值不能被修改,更加具體地說,它應該是一個指向非常量數據的常量指針。   4.2 指針數組   數組元素也可以是指針類型,指針數組常見的用途就是構成由字符串組成的數組,簡單地說就是字符串數組,數組中的每一個元素都是字符串。下面是一個例子,const限定符說明不能修改每個元素指針所指向的字符串。   [cpp]   #include<stdio.h>   int main()   {       const char *suit[4]={"Hearts","Diamonds","Clubs","Spades"};       int i;       for(i=0;i<4;i++)           printf("sizeof pointer to \"%s\" :%d\n",suit[i],sizeof(suit[i]));       printf("\nsizeof suit:%d\n",sizeof(suit));       return 0;   }   運行結果如下:   從這個例子中,可以看出const char *suit[4]={"Hearts","Diamonds","Clubs","Spades"};定義了一個指針數組,但是,其中的每個元素只是一個指針,而不是數組名(如果是數組名的話,sizeof的結果不應該都是4)。這樣定義字符串數組可以節省空間。 5、函數指針   和數組名實際上就是數組第一個元素在內存中的地址類似,函數迷你實際上就是執行函數任務的代碼在內存中的起始地址。函數指針包含函數在內存中的地址,可以傳遞給函數、從函數返回、存儲在數組中或者是賦值給其它的函數指針,下面是兩個函數指針的例子。   (1) 用函數指針實現升序/降序排序   [cpp]   #include <stdio.h>   #define SIZE 10   int ascending(int a,int b)   {       return a>b;   }   int descending(int a,int b)   {       return a<b;   }   void swap(int *aPtr,int *bPtr)   {       int temp=*aPtr;       *aPtr=*bPtr;       *bPtr=temp;   }      void bubble(int work[],const int size,int(*compare)(int a,int b))   {       int pass;       int count;       for(pass=1;pass<size;pass++)           for(count=0;count<size-pass;count++)           {               if((*compare)(work[count],work[count+1]))                   swap(&work[count],&work[count+1]);           }   }   int main()   {       int order;       int counter;       int a[SIZE]={2,6,4,8,10,12,89,68,45,37};          printf("\nData items in original order:\n");       for(counter=0;counter<SIZE;counter++)           printf("%5d",a[counter]);          printf("\nEnter 1 to sort in accending order,\n"           "Enter 2 to sort in descending order: ");       scanf("%d",&order);              if(order==1)       {           bubble(a,SIZE,ascending);           printf("\nData items in ascending order:\n");       }       else       {           bubble(a,SIZE,descending);           printf("\nData items in descending order:\n");       }       for(counter=0;counter<SIZE;counter++)           printf("%5d",a[counter]);       printf("\n");       return 0;   }       (2) 函數指針數組   [cpp]   #include<stdio.h>   void function1(int a);   void function2(int a);   void function3(int a);      int main()   {       void (*f[3])(int)={function1,function2,function3};       int choice;       printf("Enter a number between 0 and 2, 3 to end: ");       scanf("%d",&choice);       while(choice >=0 && choice<3)       {           (*f[choice])(choice);           printf("Enter a number between 0 and 2, 3 to end: ");           scanf("%d",&choice);       }       printf("Program execution completed.\n");       return 0;   }   void function1(int a)   {       printf("You entered %d so funtion1 was called\n\n",a);   }   void function2(int a)   {       printf("You entered %d so funtion2 was called\n\n",a);   }   void function3(int a)   {       printf("You entered %d so funtion3 was called\n\n",a);   }      
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved