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

C語言學習入門 (五) 指針

編輯:關於C語言

C語言學習入門 (五) 指針


直接引用

char a;

a = 10;

程序內部是怎麼操作的呢?

其實,程序對變量的讀寫操作,實際上是對變量所在的存儲空間進行寫入或取出數據。就上面的代碼而言,

系統會自動將變量名a轉換為變量的存儲地址,根據地址找到變量a的存儲空間,然後再將數據10以2進制的形式放入變量a的存儲空間中。

通過變量名引用變量,由系統自動完成變量名和其存儲地址之間的轉換,稱為變量的"直接引用"方式


間接引用

如 將變量a的地址存放在另一個變量中,比如存放在變量b中,然後通過變量b來間接引用變量a,間接讀寫變量a的值。這就是"間接引用"

總結一句:用來存放變量地址的變量,就稱為"指針變量"。在上面的情況下,變量b就是個"指針變量",我們可以說指針變量b指向變量a。

指針的定義

一般形式:類名標識符 *指針變量名;

int *p;

float *q;

  • "*"是一個說明符,用來說明這個變量是個指針變量,是不能省略的,但它不屬於變量名的一部分
  • 前面的類型標識符表示指針變量所指向的變量的類型,而且只能指向這種類型的變量

    指針的初始化

    int a = 10;int *p = &a; float b = 2.3f; float *q; q = &b;


    指針運算符

    給指針指向的變量賦值

    char a = 10;

    printf("修改前,a的值:%d\n", a);


    // 指針變量p指向變量a

    char *p = &a;//這個* 是定義指針的說明符


    // 通過指針變量p間接修改變量a的值

    *p = 9;//這個* 是指針運算符,表示 把9賦值給 指針指向的地址a,也就相當於 a = 9;

    //這裡 就是間接修改a的值

    printf("修改後,a的值:%d", a);

    取出指針所指向變量的值

    char a = 10;

    char *p;

    p = &a;


    char value = *p; //根據p值(即變量a的地址)訪問對應的存儲空間,並取出存儲的內容(即取出變量a的值),賦值給value

    printf("取出a的值:%d", value);

    使用注意

    在指針變量沒有指向確定地址之前,不要對它所指的內容賦值。下面的寫法是錯誤的


    int *p;

    *p = 10; //這是錯誤的

    應該在指針變量指向一個確定的變量後再進行賦值。下面的寫法才是正確的

    // 定義2個int型變量

    int a = 6, b;


    // 定義一個指向變量b的指針變量p

    int *p;

    p = &b;


    // 將a的值賦值給變量b

    *p = a;

    例子

    交換兩個字符變量的地址(改變實參的值)

    void swap(char *p,char *q)

    {

    char temp = *p;

    *p = *q;

    *q = temp;

    }


    int main(int argc,constchar * argv[])

    {

    char a ='A', b ='&';

    swap(&a, &b);

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

    }

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

    int a[2] = {2, 3}; int *p = &a[0]; *p = 10; 那麼 a[0]應該等於10

    數組名a 的地址 與 它的第一個元素的地址相同, 所以 p = &a[0] 與 p = a 效果一樣

    指針來遍歷數組元素

    int ary[] = {1,2,3,4, 5};

    int *q = ary;

    for (int i =0; i <5; i++)

    {

    //數組內元素內存地址是連續的存儲方式,指針移動一個對應類型單位字節數(int、char...),則指向下一個元素值

    // printf("數為:%d ", *(q+i)); //地址移動

    // printf("數為:%d ", *(ary+i)); //地址移動

    printf("數為:%d ", *(q++));//q=q+1,指針指向的地址移動

    // printf("數為:%d ", *(ary++)); //錯誤,常量不能賦值

    }


    數組、指針、函數參數

    形參數組,實參指針

    void change(int b[]) {

    b[0] = 10;

    }


    int main()

    {

    // 定義一個int類型的數組

    int a[4] = {1, 2, 3, 4};

    int *p = a;


    // 將數組名a傳入change函數中

    change(p);

    // 查看a[0]

    printf("a[0]=%d", a[0]);

    return 0;

    }

    形參指針,實參數組

    void change(int *b) {

    b[0] = 10;

    // 或者*b = 10;

    b[1] = 11;

    // 或 *(b+1) = 11;

    }


    int main()

    {

    // 定義一個int類型的數組

    int a[4] = {1, 2, 3, 4};


    // 將數組名a傳入change函數中

    change(a);

    // 查看a[0]

    printf("a[0]=%d", a[0]);

    return 0;

    } //可以看出,在很多情況下,指針和數組是可以相互切換使用的。但是,並不能說指針就等於數組


    用指針遍歷字符串的所有字符

    char chs[] ="abcde";

    char *p;

    p = chs;

    for (; *p != '\0';p++)

    {

    printf("data:%c ", *p);

    }

    printf("\n");


    用指針直接指向字符串

    char *p ="abcde";

    strlen("abde”);

    函數在string.h中的聲明

    size_t strlen(const char *);

    char *strcpy(char *,const char *);// 字符串拷貝函數

    char *strcat(char *,const char *);// 字符串拼接函數

    int strcmp(constchar *, constchar *); // 字符串比較函數

    它們的參數都是指向字符變量的指針類型,因此可以傳入指針變量或者數組名。

    指針指向字符串的其他方式

    1 char s[10];

    2 s ="mj"; //編譯器肯定報第2行的錯,因為s是個常量,代表數組的首地址,不能進行賦值運算


    1 char *s ="mj";

    2

    3 *s = "like";

    第3行代碼犯了2個錯誤:

  • 第3行代碼相當於把字符串"like"存進s指向的那一塊內存空間,由第1行代碼可以看出,s指向的是"mj"的首字符'm',
  • 也就是說s指向的一塊char類型的存儲空間,只有1個字節,要"like"存進1個字節的空間內,肯定內存溢出
  • 由第1行代碼可以看出,指針s指向的是字符串常量"mj"!因此是不能再通過指針來修改字符串內容的!
  • 就算是*s = 'A'這樣"看起來似乎正確"的寫法也是錯誤的,因為s指向的一個常量字符串,不允許修改它內部的字符。


  • char a[] ="lmj";定義的是一個字符串變量! char *p = a; *p = ‘L’; 變量可以通過指針改變,常量不行
  • char *p2 = "lmj";定義的是一個字符串常量!

    返回指針的函數

    返回指針的函數的一般形式為:類型名 *函數名(參數列表)

    // 將字符串str中的小寫字母變成大寫字母,並返回改變後的字符串

    // 注意的是:這裡的參數要傳字符串變量,不能傳字符串常量

    [plain] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
    1. char * upper(char *str) {
    2. // 先保留最初的地址。因為等會str指向的位置會變來變去的。
    3. char *dest = str;
    4. // 如果還不是空字符
    5. while (*str != '\0') {
    6. // 如果是小寫字母
    7. if (*str >= 'a' && *str <= 'z') {
    8. // 變為大寫字母。小寫和大寫字母的ASCII值有個固定的差值
    9. *str -= 'a' - 'A';
    10. }
    11. // 遍歷下一個字符
    12. str++;
    13. }
    14. // 返回字符串
    15. return dest;
    16. }
    17. int main()
    18. {
    19. //定義一個字符串變量
    20. char str[] = "lmj";
    21. // 調用函數
    22. char *dest = upper(str);
    23. printf("%s", dest);
    24. printf("%s", str);
    25. return 0;
    26. }

      指向函數的指針

      定義的一般形式:函數的返回值類型 (*指針變量名)(形式參數1,形式參數2, ...);

      注意:形式參數的變量名可以省略,甚至整個形式參數列表都可以省略

      int sum(int a,int b)

      {

      return a + b;

      }

      int main()

      {

      int (*q) (int a,int b) = sum;// (int a, int b) 可以寫成(int a, int)或(int,int)或()

      int result = (*q)(2,5);//調用函數

      printf("\n%d", result)

      return 0;

      }

      將函數作為參數

      void get(int (*q)(int a,char b), float c) {}

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