1. 程式人生 > >指標系統學習1

指標系統學習1

1.地址和指標的概念:

  記憶體區的每一個位元組有一個編號,這就是“地址” 。如果在程式中定義了一個變數,在對程式進行編譯時,系統就會給這個變數分配記憶體單元。

  在C語言中,對變數的訪問有兩種方式,直接訪問和間接訪問。

  打個比方,為了開一個A抽屜,有兩種辦法:

  • 一種方法是:將A鑰匙帶在身上,需要時直接找出該鑰匙開啟抽屜:取出所需的東西。
  • 為安全起見,將該A鑰匙放到另一抽屜B中鎖起來。如果需要開啟A抽屜,就需要先找出B鑰匙,開啟B抽屜,取出A鑰匙,再開啟A抽屜,取出A抽屜中之物。

2.關於直接訪問和間接訪問:

直接訪問如:a=5;     
        系統在編譯時,已經對變數分配了地址,例如,若變數a分配的地址是2000,則該語句的作用就是把常數5儲存到地址為2000的單元。

間接訪問如:scanf("%d",&a);
        呼叫函式時,把變數a的地址傳遞給函式scanf,函式首先把該地址儲存到一個單元中,然後把從鍵盤接收的資料通過所儲存的地址儲存到a變數中。

3.初識指標:

在C語言中,指標是一種特殊的變數,它是存放地址的。假設我們定義了一個指標變數   int *i_pointer   用來存放整型變數 i 的地址。可以通過語句:i_pointer =&i;

將i的地址(2000)存放到i_pointer中。這時, i_pointer的值就是(2000) ,即變數i所佔用單元的起始地址。要存取變數i的值,可以採用間接方式:先找到存放“i的地址”的變數i_pointer ,從中取出i的地址(2000),然後取出i的值3。

*:這玩意叫做取值操作符
&:而這玩意叫做取址操作符

如:int i = 2000;
      
int *pointer; pointer = &i; printf("%d\n", *pointer);

 

4.指標與指標變數:

知道了一個變數的地址,就可以通過這個地址來訪問這個變數,因此,又把變數的地址稱為該變數的“指標” 。

C語言中可以定義一類特殊的變數,這些變數專門用來存放變數的地址,稱為指標變數。

注意:指標變數的值(即指標變數中存放的值)是地址(即指標)。請區分“指標”和“指標變數”這兩個概念。

5.定義一個指標變數 "*":

下面都是合法的定義:
  float  *pointer_3;     // pointer_3是指向float型變數的指標變數
  char *pointer_4;      // pointer_4是指向字元型變數的指標變數

 

6.在定義指標變數時要注意兩點:

一、指標變數前面的“*”,表示該變數的型別為指標型變數。其一般形式為:
型別說明符  *變數名;

其中,*表示這是一個指標變數,變數名即為定義的指標變數名,型別說明符表示本指標變數所指向的變數的資料型別。
例如: float  *pointer_1;
指標變數名是pointer_1 ,而不是* pointer_1 。

 

二、在定義指標變數時必須指定基型別。
需要特別注意的是,只有整型變數的地址才能放到指向整型變數的指標變數中。下面的賦值是錯誤的∶

float  a;
int  * pointer_1;
pointer_1=&a;          
 /*將float型變數的地址放到指向整型變數的指標變數中,錯誤 */

 

 

7.指標變數的引用 “&”

請牢記,指標變數中只能存放地址(指標),不要將一個整數(或任何其他非地址型別的資料)賦給一個指標變數,否則編譯器也會把該值當成一個地址來處理。

C語言中提供了地址運算子&來表示變數的地址。
        其一般形式為: &變數名;

如&a表示變數a的地址,&b表示變數b的地址。當然,變數本身必須預先宣告。

/*例:通過指標變數訪問整型變數*/

void main()
{ 
    int a,b;
    int *pointer_1, *pointer_2;
    a=100; b=10;
    pointer_1 = &a;
    pointer_2 = &b;

    printf("%d,%d\n",a,b);
    printf("%d,%d\n",*pointer_1, *pointer_2);
}

 

8.對“&”和“*”運算子再做些說明:
如果已執行了語句   pointer_1=&a;
(1)&* pointer_1的含義是什麼?
  “&”和“*”兩個運算子的優先級別相同,但按自右而左方向結合,因此先進行* pointer_1的運算,它就是變數a,再執行&運算。因此,&* pointer_1與&a相同,即變數a的地址。
  如果有:pointer_2 =&* pointer_1;它的作用是將&a(a的地址)賦給pointer_2 ,如果 pointer_2 原來指向b,經過重新賦值後它已不再指向b了,而指向了a。
  請看圖解!

(2) *&a的含義是什麼?

  先進行&a運算,得a的地址,再進行*運算。即&a所指向的變數,也就是變數a。*&a和*pointer_1的作用是一樣的,它們都等價於變數a。即*&a與a等價。

 

(3) (*pointer_1)++相當於a++。
  注意括號是必要的,如果沒有括號,就成為了*pointer_1++,從附錄可知:++和*為同一優先級別,而結合方向為自右而左,因此它相當於*(pointer_1++)。
  由於++在pointer_1的右側,是“後加”,因此先對pointer_1的原值進行*運算,得到a的值,然後使pointer_1的值改變,這樣pointer_1不再指向a了。

 

9.例題:

題目:輸入a和b兩個整數,按先大後小的順序輸出a和b。

#include <stdio.h>

void main()
{ 
      int *p1, *p2, *p, a, b;

      scanf("%d %d", &a, &b);
      p1 = &a;
      p2 = &b;
      
      if( a < b)     
      {
            p = p1;
            p1 = p2;
            p2 = p;
      } //此後,p1指向b, p2指向a ^_^
      
      printf("a = %d, b = %d\n", a, b);
      printf("max = %d, min = %d\n", *p1, *p2);
}

 

題目:對輸入的兩個整數按大小順序輸出!這次用函式實現交換功能!

#include <stdio.h>

void swap(int *p1, int *p2);

void main()
{ 
      int a, b;
      int *pointer_1, *pointer_2;
      
      scanf("%d %d", &a, &b);
      
      pointer_1 = &a;
      pointer_2 = &b;
      
      if(a < b) 
      {
            swap(pointer_1, pointer_2); //swap實現的是交換……
      }
      
      printf("\n%d > %d\n", a, b);
      
}

void swap(int *p1, int *p2)
{
      int temp;

      printf("I'm swapping……\n");
      printf("Please wait^_^");
      
      temp = *p1;  //temp = a;
      *p1 = *p2;   //a = b;
      *p2 = temp;  //b = temp;
      
}