C語言 指針

1、C語言 指針基礎

一、內存地址

一、內存含義數組

  • 存儲器:計算機的組成中,用來存儲程序和數據,輔助CPU進行運算處理的重要部分。
  • 內存:內部存貯器,暫存程序/數據——掉電丟失 SRAM、DRAM、DDR、DDR二、DDR3。
  • 外存:外部存儲器,長時間保存程序/數據—掉電不丟ROM、ERRROM、FLASH(NAND、NOR)、硬盤、光盤。

二、內存是溝通CPU與硬盤的橋樑ide

  • 暫存放CPU中的運算數據
  • 暫存與硬盤等外部存儲器交換的數據

三、物理存儲器和存儲地址空間函數

  • 有關內存的兩個概念:物理存儲器和存儲地址空間

四、物理存儲器:實際存在的具體存儲器芯片編碼

  • 主板上裝插的內存條
  • 顯示卡上的顯示RAM芯片
  • 各類適配卡上的RAM芯片和ROM芯片

五、存儲地址空間:對存儲器編碼的範圍。咱們在軟件上常說的內存是指這一層含義spa

  • 編碼:對每一個物理存儲單元(一個字節)分配一個號碼
  • 尋址:能夠根據分配的號碼找到相應的存儲單元,完成數據的讀寫

六、內存地址操作系統

  • 將內存抽象成一個很大的一維字符數組。
  • 編碼就是對內存的每個字節分配一個32位或64位的編號(與32位或者64位處理器相關)。
  • 這個內存編號咱們稱之爲內存地址。

七、內存中的每個數據都會分配相應的地址指針

  • char:佔一個字節分配一個地址
  • int: 佔四個字節分配四個地址
  • float、struct、函數、數組等

二、指針變量

1、概述

  • 內存區的每個字節都有一個編號,這就是「地址」。
  • 若是在程序中定義了一個變量,在對程序進行編譯或運行時,系統就會給這個變量分配內存單元,並肯定它的內存地址(編號)
  • 指針的實質就是內存「地址」。指針就是地址,地址就是指針。
  • 指針是內存單元的編號,指針變量是存放地址的變量。
  • 一般咱們敘述時會把指針變量簡稱爲指針,實際他們含義並不同。

2、數據存儲格式

注:windos電腦在作數據存儲時採用小端對齊。blog

注:Linux 電腦在作數據存儲時採用大端對齊。排序

3、定義說明

  • 指針也是一種數據類型,指針變量也是一種變量
  • 指針變量指向誰,就把誰的地址賦值給指針變量
  • 「*」操做符操做的是指針變量指向的內存空間

注意:&能夠取得一個變量在內存中的地址。可是,不能取寄存器變量,由於寄存器變量不在內存裏,而在CPU裏面,因此是沒有地址的。
注意:&是取地址符號是升維度的、*是取值符號是將維度的。
注意:在定義指針類型必定要和變量的類型對應上。內存

4、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定義指針變量存儲變量地址
    int a = 10;
    // 指針類型:數據類型*
    int* p;
    p = &a;
    // 經過指針間接改變變量的值
    *p = 100;
    printf("%p\n", &a);
    printf("%p\n", p);
    printf("%d\n", a);
    printf("%d\n", *p);
    return 0;
}
指針變量 使用案例:int類型指針修改值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    char ch = 'a';
    char* p = &ch;

    // 全部指針類型存儲都內存地址,內存地址都是一個無符號十六進制整形數
    // 32位操做系統全部指針類型:內存佔用4字節
    // 64位操做系統全部指針類型:內存佔用8字節
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(char*));

    return 0;
}
指針變量 使用案例:指針在內存中佔用字節大小
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    
    // P 和 arr 不一樣點
    // 指向數組指針
    int* p = arr;

    // 相同點
    //p[i]
    //*(p+i)

    // 不一樣點
    // p 是變量、arr是常量
    // p 是一個指針4個字節大小
    // arr 是一個數組是40個字節大小
    printf("指針類型大小%d\n", sizeof(p));
    printf("數組大小%d\n", sizeof(arr));
    
    // 數組做爲函數參數會化爲指針、丟失數組的精度
    // 經過 int* 將指針變爲值
    // void BubbleSort(int arr[])
    // void BubbleSort(int* arr[],int len)

    return 0;
}
指針變量 使用案例:指針與變量不一樣點

三、野指針

  指針變量也是變量,是變量就能夠任意賦值,不要越界便可(32位爲4字節,64位爲8字節),可是,任意數值賦值給指針變量沒有意義,由於這樣的指針就成了野指針,此指針指向的區域是未知(操做系統不容許操做此指針指向的內存區域)。因此,野指針不會直接引起錯誤,操做野指針指向的內存區域纔會出問題。野指針和有效指針變量保存的都是數值,爲了標誌此指針變量沒有指向任何變量(空閒可用)

       int a = 100;
       int *p;
       p = a; //把a的值賦值給指針變量p,p爲野指針, ok,不會有問題,但沒有意義
 
       p = 0x12345678; //給指針變量p賦值,p爲野指針, ok,不會有問題,但沒有意義
 
       *p = 1000;  //操做野指針指向未知區域,內存出問題,err

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 野指針 -> 指針變量指向一個未知的空間
    // 不建議將一個變量的值直接賦值給指針
    // 程序中容許存在野指針
    int* p = 100;
    // 操做系統將0-255做爲系統佔用不容許訪問操做
    // 操做野指針對應的內存空間可能報錯
    printf("%d\n", *p);

    return 0;
}
野指針 使用案例

四、空指針

C語言中,能夠把NULL賦值給此指針,這樣就標誌此指針爲空指針,沒有任何指針。

// 空指針
int *p = NULL;
 
// NULL是一個值爲0的宏常量:
#define NULL    ((void *)0)

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 空指針是指內存地址編號爲0的空間
    int* p = NULL;
    // 操做空指針對應的空間必定會報錯
    *p = 100;
    printf("%d\n", *p);
    // 空指針能夠用做條件判斷
    if (p == NULL)
    {
        
    }
    return 0;
}
空指針 使用案例

五、萬能指針

void *指針能夠指向任意變量的內存空間。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int a = 10;
    // 萬能指針能夠接受任意類型變量的內存地址
    void * p = &a;
    // 再經過萬能指針修改變量的值時,須要找到變量對應的指針類型
    *(int*)p = 100;
    printf("%d\n", a);
    printf("%d\n", *(int*)p);
    // printf("萬能指針在內存佔得字節大小:%d\n", sizeof(void*));
    return 0;
}
萬能指針 使用案例

六、const 修飾指針

const 修飾能夠約束指針類型或值得修改,但使用+1級別指針也可讓const無效。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 一、
    // 常量:不容許修改
    // 存儲空間:棧區(可指針間接修改)
    const int a = 10;

    // 指針間接修改常量值
    int* p = &a;
    *p = 100;
    printf("%d\n", a);

    // 二、
    // const 修飾指針類型(內存空間)
    int a = 10;
    int b = 20;
    const int* p = &a;

    // 能夠修改指針變量的值
    // 不能夠修改指針內存空間的值:*p = 100;
    p = &b;
    printf("%d\n", *p);

    // 三、
    // const 修飾指針變量
    int c = 10;
    int d = 20;
    int* const p = &c;

    // 能夠修改指針類型(內存空間)的值
    // 不能夠修改指針內存空間的值:p = &d;
    *p = 100;
    printf("%d\n", *p);


    // 四、
    // const 修飾指針變量、類型(內存空間)
    // 只讀指針
    int e = 10;
    int f = 20;
    // 不能夠修改指針內存空間的值:*p = 100;
    // 不能夠修改指針內存空間的值:p = &f;
    const int* const p = &e;

    // 二級指針操做
    // 可經過二級指針修改一級指針內存空間的值:
    int** pp = &p;
    // *pp是一級指針的值(內存空間)
    *pp = &b;
    // **pp是變量的值、**表明將了一個維度
    **pp = 100;
    printf("%d\n", *p);


    return 0;
}
const修飾指針 使用案例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(void)
{
       //const修飾一個變量爲只讀
       const int a = 10;
       //a = 100; //err
 
       //指針變量, 指針指向的內存, 2個不一樣概念
       char buf[] = "aklgjdlsgjlkds";
 
       //從左往右看,跳過類型,看修飾哪一個字符
       //若是是*, 說明指針指向的內存不能改變
       //若是是指針變量,說明指針的指向不能改變,指針的值不能修改
       const char *p = buf;
       // 等價於上面 char const *p1 = buf;
       //p[1] = '2'; //err
       p = "agdlsjaglkdsajgl"; //ok
 
       char * const p2 = buf;
       p2[1] = '3';
       //p2 = "salkjgldsjaglk"; //err
 
       //p3爲只讀,指向不能變,指向的內存也不能變
       const char * const p3 = buf;
 
       return 0;
}
const修飾指針 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定義int類型
    const int a = 10;
    // 直接不能夠修改
    // a = 100; //err
    // 經過一級指針修改
    int* p = &a;
    *p = 100;

    // 定義char類型
    char ch1[] = "hello";
    char ch2[] = "hello";
    // 指向常量指針:能夠修改指針變量的值、不能夠修改指針變量指向內存空間的值
    const char* p = ch1;
    // *p = 'm';//err
    // p = ch2;//ok
    // p[2] = 'm';//err

    // 定義char類型
    char ch3[] = "hello";
    char ch4[] = "hello";
    // 常量指針:能夠修改指針變量指向內存空間的值、不能夠修改指針變量的值
    char* const p = ch3;
    // p = ch4;//err
    // p[2] = 'm';//ok
    // *(p + 2) = 'm';//ok

    // 定義char類型
    char ch5[] = "hello";
    char ch6[] = "hello";
    // 不可修改變量與內存
    const char* const p = ch5;
    // p = ch6;//err
    // p[2] = 'm';//err
    // *p = 'm';//err
    // 二級指針
    char** p1 = &p;
    // *p1 = ch2;//ok
    // *(*p1+1) = 'm';//ok

    return 0;
}
const修飾指針 使用案例:3
2、C語言 指針使用

一、指針類型運算

  • 指針計算不是簡單的整數相加
  • 若是是一個int *,+1的結果是增長一個int的大小
  • 若是是一個char *,+1的結果是增長一個char大小

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    
    // 數組名是一個常量 不容許賦值
    // 數組名是數組首元素地址
    // aar = 100; //err
    // 建立指針變量
    int* p;
    p = arr;
    printf("%p\n", p);

    // 打印數組第一個值
    printf("%d\n", *p);
    printf("%p\n", arr);

    // *取值(arr內存地址+1) 、至關於arr[1]
    printf("%d\n", *(arr + 1));

    // 指針類型變量+1:等同於內存地址+sizeof(類型)
    printf("%d\n", *(p + 1));

    // 指針p++:等同於內存地址+sizeof(類型)
    *p = 123;
    p++;
    printf("%p\n", arr);
    printf("%p\n", p);

    for (int i = 0; i < 10; i++)
    {
        // 打印數組值
        printf("%d\n", p[i]);
        printf("%d\n", *(p + i));

        // 打印數組值
        printf("%d\n", *p++);
    }

    // 兩個指針相減 獲得的結果是兩個指針的偏移量(步長)
    // 全部的指針類型 相減結果都是int類型
    // 3c 40 +1 至關於 sizeof(int) 40/sizeof(int)
    int step = p - arr;
    printf("%d\n", step);


    return 0;
}
指針類型運算 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 方式一:數組方式實現
void my_strcpy01(char* dest, char* ch)
{
    int i = 0;
    // 非0爲真值
    while (ch[i])
    {
        dest[i] = ch[i];
        i++;
    }
    dest[i] = 0;
}

// 方式二:以指針偏移量
void my_strcpy02(char* dest, char* ch)
{
    int i = 0;
    while (*(ch+i))
    {
        *(dest + i) = *(ch + i);
        i++;
    }
    *(dest + i) = 0;
}

// 方式三:以指針運算方式實現
void my_strcpy03(char* dest, char* ch)
{
    while (*ch)
    {
        *dest = *ch;
        // 指針+1至關於指向數組下一個元素 內存地址變化了sizeof(char)
        dest++;
        ch++;
    }
    *dest = 0;
}

// 方式四:以指針加運算方式實現
void my_strcpy04(char* dest, char* ch)
{
    // 第一步:*ch 取值 *dest 取值
    // 第二部:*dest = *ch 賦值
    // 第三部:判斷 值是否非0
    // 第四部:ch++ dest++
    while (*dest++ = *ch++);
}

int main(void)
{
    // 指針運算、字符串拷貝
    char ch[] = "hello world";
    char dest[100];
    my_strcpy04(dest, ch);
    printf("%s\n", dest);

    return 0;
}
指針類型運算 使用案例:指針加法運算
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;
    
    // 指針的加減運算和指針的類型有關
    p = &arr[3];
    p--;
    p--;
    p--;

    // 內存地址相差:12 / sizeof(int) = 偏移量
    int step = p - arr;

    // 指針操做數組時下標容許時負數
    // p[-2] = *(p-2);
    printf("%d\n", p[-2]);
    printf("%p\n", p);

    return 0;
}
指針類型運算 使用案例:指針減法運算
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 指針和運算符的操做
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;

    // 野指針
    // p = p + arr; //err
    // p = p*arr; //err
    // p = p*4; //err
    // p = p/4; //err
    // p = p%4; //err

    // 指針判斷可使用、> = < ? && || ...
    // p = &arr[3]
    // if (p > arr) { printf("真\n");}

    // 野指針能夠相減
    // p = 100;
    // int step = arr - p;
    ///printf("%d\n",step)

    return 0;
}
指針類型運算 使用案例:指針符號運算

二、指針數組

指針數組,它是數組,數組的每一個元素都是指針類型。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 定義數組 數據類型 數據名[元素個數] = {值1,值2}
    // 定義指針數組
    int a = 10;
    int b = 20;
    int c = 30;
    int* arr[3] = { &a,&b,&c };

    // arr[0]:爲指針數組地址
    // *arr[0]:爲指針對應值
    printf("%d\n", arr[0]);
    printf("%d\n", *arr[0]);

    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        // 打印數組內每一個值
        printf("%d\n", *arr[i]);
    }

    // 指針數組大小 = 對應類型 * 元素個數 
    printf("指針數組大小:%d\n", sizeof(arr));
    printf("指針數組大小:%d\n", sizeof(arr[0]));

    return 0;
}
指針數組 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 指針數組裏面元素存儲的是指針
    int a[] = { 1,2,3 };
    int b[] = { 4,5,6 };
    int c[] = { 7,8,9 };

    // 指針數組時一個特殊的二維數組模型
    // 指針數組對應於二級指針
    int* arr[] = { a,b,c };

    // 打印內存地址
    // arr 是指針數組的首地址
    printf("%p\n", arr[0]);
    printf("%p\n", a);
    printf("%p\n", &a[0]);


    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            // 經過二維數組方式打印全部值
            printf("%d", arr[i][j]);
            // 經過偏移量方式打印
            printf("%d", *(arr[i]+j));
            // 經過偏移量與指針運算方式打印
            printf("%d", *(*(arr + i) + j));
        }
        puts("");
    }
    return 0;
}
指針數組 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
// 數組名作函數參數,函數的形參會退化爲指針
// 經過數組寫法實現
void my_strcat01(char* ch1, char* ch2)
{
    int i = 0;
    while (ch1[i] != '\0')
    {
        i++;
    }
    int j = 0;
    while (ch2[j] != '\0')
    {
        ch1[i + j] = ch2[j];
        j++;
    }
    ch1[i + j] = 0;
}

// 經過指針加偏移量方式實現1
void my_strcat02(char* ch1, char* ch2)
{
    int i = 0;
    while (ch1[i] != '\0')
    {
        i++;
    }
    int j = 0;
    while (*(ch2 + j) != '\0')
    {
        *(ch1 + i + j) = *(ch2 + j);
        j++;
    }
    ch1[i + j] = 0;
}

// 經過指針加偏移量方式實現2
void my_strcat03(char* ch1, char* ch2)
{
    while (*ch1)ch1++;
    while (*ch1++ = *ch2++);
}

int main(void)
{
    char ch1[100] = "hello";
    char ch2[] = "world";
    my_strcat02(ch1, ch2);
    printf("%s\n", ch1);

    return 0;
}
指針數組 使用案例:數組名做爲函數參數

三、多級指針

  • C語言容許有多級指針存在,在實際的程序中一級指針最經常使用,其次是二級指針。
  • 二級指針就是指向一個一級指針變量地址的指針。
  • 三級指針基本用不着
int a = 10;
int *p = &a; //一級指針
*p = 100; //*p就是a
 
int **q = &p;
//*q就是p
//**q就是a
 
int ***t = &q;
//*t就是q
//**t就是p
//***t就是a

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    int a[] = { 1,2,3 };
    int b[] = { 4,5,6 };
    int c[] = { 7,8,9 };
    int* arr[] = { a,b,c };

    // 指針數組和二級指針創建關係
    int** p = arr;

    // 對應:arr[0][0]、a[0]
    printf("%d\n", **p);

    // 二級指針加偏移量:至關於跳過了一個覺得數組大小
    // 一級指針加偏移量:至關於跳過了一個元素
    //對應:arr[0][1]、a[1]
    printf("%d\n", *(*p+1));
    //對應:arr[1][1]、b[1]
    printf("%d\n", *(*(p + 1) + 1));

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            // 經過偏移量與指針運算方式打印
            printf("%d", *(*(arr + i) + j));
        }
        puts("");
    }
    return 0;
}
多級指針 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{

    //*ppp==**pp==&p
    //**ppp==*pp=p==&a
    //***ppp==**pp==*p=a
    int a = 10;
    int b = 20;
    int* p = &a;
    int** pp = &p;
    int*** ppp = &pp;


    // pp:二級指針變量的值
    // *pp:一級指針的值
    // **pp:變量的值

    // 等價於:p=&b
    // *pp = &b;

    // 等價於:a = 100
    //**pp = 100;

    // 野指針
    // *p = 100;

    printf("%d\n", *p);
    return 0;
}
多級指針 使用案例:2

四、字符指針

字符指針經過指針處理字符

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 棧區字符串
    char ch[] = "hello world";
    
    // 數據區常量區字符串、不容許修改內容
    // hello world 對應內存地址爲只讀,大小相同
    char* p = "hello world";
    char* p1 = "hello world";

    // ch[2] = 'm'; // 可修改
    // p[2] = 'm'; //err

    return 0;
}
字符指針 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 樣式一
    // 能夠作修改
    // 指針數組
    char ch1[] = "hello";
    char ch2[] = "world";
    char ch3[] = "dabaobei";
    char* arr1[] = { ch1,ch2,ch3 };

    // 樣式二
    // 不能作修改、但能夠排序
    // 字符串數組
    char* arr2[] = { "hello","wojjrld","zzzzz" };

    // 字符串排序
    for (int i = 0; i < 3 - 1; i++)
    {
        for (int j = 0; j < 3 - 1 - i; j++)
        {
            // 找首字符進行比較
            if (arr2[j][0]>arr2[j + 1][0])
            {
                // 交換指針數組進行排序
                char* temp = arr2[j];
                arr2[j] = arr2[j + 1];
                arr2[j + 1] = temp;
            }
        }
    }

    // 打印
    for (int i = 0; i < 3; i++)
    {
        printf("%s\n", arr2[i]);
    }
    return 0;
}
字符指針 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 數組實現
int my_strlen01(char* ch)
{
    // 計算字符串有效長度
    int i = 0;
    while (ch[i] != '\0')i++;
    return i;
}

// 指針實現
int my_strlen02(char* ch)
{
    char* temp = ch;
    while (*temp != '\0')temp++;
    return temp - ch;
}

int main(void)
{
    char ch[] = "hello world";
    int len = my_strlen02(ch);
    printf("%d\n", len);
    return 0;
}
字符指針 使用案例:字符指針做爲函數參數
3、案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 指針做爲函數參數傳遞
void swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main(void)
{

    int a = 10;
    int b = 20;

    // 值傳遞
    // 形參不影響實參的值
    // swap(a, b);

    // 地址傳遞
    // 形參能夠改變實參的值
    swap(&a, &b);

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

    return 0;
}
指針 使用案例:值傳遞和地址傳遞
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

void remove_space(char* ch)
{
    // 便利字符串有效個數
    char* ftemp = ch;
    // 記錄非空格字符串
    char* rtemp = ch;
    while (*ftemp)
    {
        if (*ftemp != ' ')
        {
            *rtemp = *ftemp;
            rtemp++;
        }
        ftemp++;
    }
    *rtemp = 0;
}

int main(void)
{
    char ch[] = "  h  e  ll  o  w o r lld";
    remove_space(ch);
    printf("%s\n", ch);
    return 0;
}
指針 使用案例:字符串去空格
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 數組方式
char* my_strchr01(char* str,char ch)
{
    int i = 0;
    while (str[i])
    {
        if (str[i] == ch)
        {
            return &str[i];
        }
        i++;
    }
    return NULL;
}

// 指針方式
char* my_strchr02(char* str, char ch)
{
    while (*str)
    {
        if (*str == ch)
        {
            return str;
        }
        str++;
    }
    return NULL;
}

int main(void)
{
    char str[] = "hello world";
    char* p = my_strchr02(str,'w');
    if (p == NULL)
    {
        printf("未找到:");
    }
    printf("%s\n", p);
    return 0;
}
指針 使用案例:指針作爲函數的返回值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

char* my_strchr(char* src, char* dest)
{
    // 用於循環便利源字符串指針
    char* fsrc = src;
    // 記錄每次相同字符串首地址
    char* rsrc = src;
    char* tdest = dest;
    while (*fsrc)
    {
        rsrc = fsrc;
        while (*fsrc == *tdest && *fsrc!='\0')
        {
            fsrc++;
            tdest++;
        }
        if (*tdest == '\0')
        {
            return rsrc;
        }
        // 回滾
        // 目標字符串更新到起始位置
        tdest = dest;
        fsrc = rsrc;
        fsrc++;
    }
    return NULL;
}

int main(void)
{
    char src[] = "hello world";
    char dest[] = "llo";
    char* p = my_strchr(src,dest);
    printf("%s\n", p);
    return 0;
}
指針 使用案例:模糊查詢
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 數組實現
int getstrcount01(char* ch)
{
    int i = 0;
    int count = 0;
    while (ch[i])
    {
        if (ch[i] != ' ')
        {
            count++;
        }
        i++;
    }
    return count;
}

// 指針實現
int getstrcount02(char* ch)
{
    int count = 0;
    while (*ch)
    {
        if (*ch != ' ')count++;
        ch++;
    }
    return count;
}

int main(void)
{
    char ch[] = "    hello world    ";
    int len = getstrcount(ch);
    printf("%d\n", len);
    return 0;
}
指針 使用案例:求非空字符串元素的個數
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    //97+26 ASCLL碼 
    // 統計字符串出現次數
    char ch[] = "helloworldfdjklfdjklfdsajklfdsa dsa";
    
    // 存儲字符串出現次數
    int arr[26] = {0};
    
    for (int i = 0; i < strlen(ch); i++)
    {
        // ASCLL碼 a - 字符、++:每找到一個相同就+1
        arr[ch[i] - 'a']++;
    }

    for (int i = 0; i < 26; i++)
    {
        if(arr[i])
            printf("字母:%c出現次數:%d\n", i + 'a', arr[i]);
    }
    return 0;
}
指針 使用案例:統計字符個數
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 數組實現
void inverse01(char* ch)
{
    int i = 0;
    int j = strlen(ch) - 1;
    while (i < j)
    {
        char temp = ch[i];
        ch[i] = ch[j];
        ch[j] = temp;
        i++;
        j--;
    }
    return;
}

// 指針實現
void inverse02(char* ch)
{
    char* ftemp = ch;
    char* btemp = ch + strlen(ch) - 1;
    while (ftemp<btemp)
    {
        char temp = *ftemp;
        *ftemp = *btemp;
        *btemp = temp;
        ftemp++;
        btemp--;
    }
    return;
}

int main(void)
{
    char ch[] = "hello world";
    inverse02(ch);
    printf("%s\n", ch);
    return 0;
}
指針 使用案例:字符串逆質
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int symm(char* ch)
{
    char* ftemp = ch;
    char* btemp = ch + strlen(ch) - 1;
    while (ftemp < btemp)
    {
        if (*ftemp!=*btemp)
        {
            return 1;
        }
        ftemp++;
        btemp--;
    }
    return 0;
}

// 判斷:迴文字符串
int main(void)
{
    char ch[] = "abcba";
    int value = symm(ch);
    if (!value)
    {
        printf("相同\n");
    }
    else
    {
        printf("不相同\n");

    }
    return 0;
}
指針 使用案例:判斷迴文字符串
相關文章
相關標籤/搜索