中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

C語(yǔ)言中多種指針相關(guān)類型詳解-創(chuàng)新互聯(lián)

目錄

創(chuàng)新互聯(lián)是一家專業(yè)提供南樂(lè)企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都做網(wǎng)站、H5開(kāi)發(fā)、小程序制作等業(yè)務(wù)。10年已為南樂(lè)眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。

指針數(shù)組

數(shù)組指針

arr與&arr的區(qū)別

數(shù)組指針

1.數(shù)組指針的創(chuàng)建格式:

2.數(shù)組指針的用處

數(shù)組參數(shù),指針參數(shù)

一維數(shù)組傳參

二維數(shù)組傳參(注意事項(xiàng))

一級(jí)指針傳參

二級(jí)指針傳參

函數(shù)指針

函數(shù)指針數(shù)組

函數(shù)指針真正用處用法


指針數(shù)組

指針數(shù)組是指在一組數(shù)中能夠存放多個(gè)相同指針類型的一組數(shù)

指針數(shù)組的書(shū)寫(xiě)格式:

  • int* * *arr[5];——存放int *類型的數(shù)組
  • char* ch[10];——存放char *類型的數(shù)組
  • int** pp[5];——存放int** 二級(jí)指針類型的數(shù)組

當(dāng)然還可以類比出三級(jí)指針,四級(jí)指針等等等等....

指針的初始化:

如int* arr[5]={0};

在這里我們將數(shù)組arr里的每一個(gè)元素賦了0,也就相當(dāng)于將指針數(shù)組里面的所有元素都變?yōu)榱丝罩羔槪@是因?yàn)樵诰幾g器中,NULL相當(dāng)于0被強(qiáng)制類型轉(zhuǎn)換為了(void*)類型,所以NULL本質(zhì)上就是0。

數(shù)組指針

數(shù)組指針是一種指針類型,是一個(gè)指向數(shù)組的指針。

數(shù)組指針的書(shū)寫(xiě)格式:

#includeint main()
{
    int arr[5]={0};
    char s[5]={0};
    int (*p)[5]=&arr;//這個(gè)就是數(shù)組指針的格式,
                     //也可以用其他類型如char等
    char (*b)[5]=&s;
    return 0;
}
arr與&arr的區(qū)別

創(chuàng)造一個(gè)int型數(shù)組int arr[5]={0}; 我們都知道arr是數(shù)組名,也就是首元素的地址,但&arr表示的是什么?

在編譯器中輸入以下代碼:

#includeint main()
{
  int arr[5] = { 0 };
  printf("%p\n", arr);
  printf("%p\n",arr + 1);
  printf("%p\n", &arr);
  printf("%p\n", &arr + 1);
  return 0;
}

最終輸出結(jié)果如下:

觀察上面的輸出后的圖,我們可以看到arr與&arr的地址是相同的,但arr與&arr其實(shí)是兩個(gè)完全不同的概念。

我們可以看到,arr+1后的地址與arr的地址相差了4,這是因?yàn)閍rr是數(shù)組名,相當(dāng)于存放了數(shù)組首元素的地址,也就是一個(gè)int*類型的指針,所以每加一后都會(huì)直接跳過(guò)四個(gè)字節(jié),讀取到數(shù)組中下一個(gè)元素。而我們?cè)倏聪?arr與&arr+1的地址,經(jīng)過(guò)計(jì)算后得到兩地址相差的數(shù)值大小為20,我們會(huì)發(fā)現(xiàn),這剛好是我們創(chuàng)建數(shù)組的所占的總共空間大?。?0個(gè)字節(jié))。

也就是說(shuō),&arr其實(shí)取到的并不是數(shù)組首元素地址,類型并不為int*指針,而取到的是整個(gè)數(shù)組的地址,類型為數(shù)組指針,所以當(dāng)我們加一的時(shí)候,由于是數(shù)組指針加一,所以會(huì)跳過(guò)20個(gè)字節(jié)。那么數(shù)組指針具體又是什么呢?

數(shù)組指針

就像int型會(huì)有int指針,char類型有char指針,數(shù)組也會(huì)有對(duì)應(yīng)的數(shù)組指針,例如int型數(shù)組,數(shù)組指針的書(shū)寫(xiě)格式就為int(*)[],具體用法如下:

數(shù)組指針的應(yīng)用

1.數(shù)組指針的創(chuàng)建格式:

2.數(shù)組指針的用處

Ⅰ:訪問(wèn)一維數(shù)組

#includeint main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int(*p)[10] = &arr;
  int i = 0;
  for (i = 0; i< 10; i++)
  {
    printf("%d ",*((*p) + i));
  }
  return 0;
}

這里雖然訪問(wèn)一維數(shù)組用這種方法繁冗且不建議使用,但還是做下解釋。

Ⅱ:訪問(wèn)二維數(shù)組

如果要寫(xiě)一個(gè)函數(shù),將遍歷二維數(shù)組將每一個(gè)元素打印出來(lái),我們會(huì)怎么寫(xiě)呢?

在以前會(huì)使用下面的方法:

#includevoid print(int a[3][5], int x, int y)
{
  int i = 0;
  int j = 0;
  for (i = 0; i< x; i++)
  {
    for (j = 0; j< y; j++)
    {
      printf("%d ", a[i][j]);
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };
  print(arr, 3, 5);
  return 0;
}

但現(xiàn)在,我們可以用數(shù)組指針的方式來(lái)實(shí)現(xiàn):

#includevoid print(int(*p)[5], int x, int y)
{
  int i = 0;
  int j = 0;
  for (i = 0; i< x; i++)
  {
    for (j = 0; j< y; j++)
    {
      printf("%d ", *(*(p + i) + j));
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };
  print(arr, 3, 5);
  return 0;
}

在二維數(shù)組中例如arr[3][5],其中的“[3]”所代表的是有3行元素,“[5]”代表的是每行元素有5列。而arr[5]則代表一行的地址

所以當(dāng)我們?cè)趥鲄r(shí),只需要將形參定為int型的指針數(shù)組,先將每一行的地址傳入,就可以實(shí)現(xiàn)遍歷數(shù)組的作用。

再次理解:

#includeint main()
{
  int a[10] = { 0 };
  int* p = a;
  //*(a+i)==*(p+i)==a[i]==p[i]
}
數(shù)組參數(shù),指針參數(shù) 一維數(shù)組傳參

看下面代碼,判斷傳參是否正確:

#includevoid test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int *arr)//ok?
{}
void test2(int *arr[20])//ok?
{}
void test2(int **arr)//ok?
{}
int main()
{
    int arr[10]={0};
    int *arr2[20]={0};
    test(arr);
    test2(arr2);
    return 0;
}

一維數(shù)組傳參經(jīng)驗(yàn)總結(jié):

  • 在數(shù)組傳參時(shí)可以使用數(shù)組形式,而且數(shù)組后可以寫(xiě)大小也可不寫(xiě),因?yàn)閿?shù)組在傳參過(guò)程中不會(huì)創(chuàng)建數(shù)組,所以數(shù)組大小填錯(cuò)或不填都可以
  • 數(shù)組傳參傳入的數(shù)組名是首元素地址,可以用指針來(lái)接收

所以上述代碼中的傳參都是正確的。

二維數(shù)組傳參(注意事項(xiàng))

看下面代碼,判斷傳參是否正確:

#includevoid test(int arr[3][5])//ok?  ----1
{}
void test(int arr[][])//ok?    ----2
{}
void test(int arr[][5])//ok?   ----3
{}
void test(int *arr)//ok?       ----4
{}
void test(int (*arr)[5])//ok?  ----5
{}
void test(int **arr)//ok?      ----6
{}
int main()
{
    int arr[3][5]={0};
    test(arr);
}

二維數(shù)組傳參經(jīng)驗(yàn)總結(jié):

  • 二維數(shù)組傳參時(shí)可以寫(xiě)成形參二維數(shù)組的形式,行可以不寫(xiě)大小,但是列一定要寫(xiě)大小。
  • 在傳參時(shí)傳入的是數(shù)組指針類型,所以不能用一級(jí)指針接收,也不能用指針數(shù)組、二級(jí)指針來(lái)接收,這樣是類型上就不對(duì)的了

綜上,2,4,6是錯(cuò)誤的傳參形式。

一級(jí)指針傳參

Q:當(dāng)函數(shù)的參數(shù)為一級(jí)指針時(shí),函數(shù)能接收什么參數(shù)?

A:可以傳入一個(gè)地址,或數(shù)組名,或直接傳入一個(gè)一級(jí)指針。

二級(jí)指針傳參

Q:當(dāng)函數(shù)的參數(shù)為二級(jí)指針時(shí),函數(shù)能接收什么參數(shù)?

A:可以傳入一級(jí)指針的地址、二級(jí)指針、指針數(shù)組的數(shù)組名。

函數(shù)指針

函數(shù)不同于數(shù)組,函數(shù)名與在函數(shù)名前加上&本質(zhì)上是沒(méi)有區(qū)別的,下面是函數(shù)指針的一些使用:

#includeint Add(int x, int y)
{
  return x + y;
}
void Fun(char x)
{
  ;
}
int main()
{
  //Add與&Add本質(zhì)上沒(méi)有區(qū)別,都表示為同一個(gè)地址
  printf("%p\n", Add);
  printf("%p\n", &Add);
  //函數(shù)指針的創(chuàng)建舉例
  int (*p)(int, int) = Add;
  int (*pa)(int, int) = &Add;
  void (*ppa)(char) = Fun;
  //函數(shù)指針的調(diào)用也同函數(shù)名一樣,可以直接用名或者在前面加上解引用符
  printf("%p\n", p);
  printf("%p\n", *p);
  //函數(shù)的調(diào)用
  printf("%d\n", Add(1, 2));
  printf("%d\n", (&Add)(1, 2));//這里特別注意,要將&Add用小括號(hào)括起來(lái),否則Add就會(huì)先與后面的(1,2)結(jié)合,從而無(wú)法調(diào)用函數(shù)。
  printf("%d\n", p(1, 2));
  printf("%d\n", (*p)(1, 2));//*p也是先要用小括號(hào)括起來(lái),否則會(huì)與后面的(1,2)結(jié)合,從而無(wú)法調(diào)用函數(shù)得到想得到的結(jié)果。
  return 0;
}

特別注意:以上面代碼為例,若要以&Add或者*p這種形式來(lái)使用,要先用小括號(hào)括起來(lái),否則Add/p就會(huì)先與后面的(1,2)結(jié)合,從而無(wú)法調(diào)用函數(shù)。

在學(xué)習(xí)函數(shù)指針時(shí),又偶然發(fā)現(xiàn)了一道很經(jīng)典,非常,特別,詭異的題目:

//請(qǐng)分析下面這段代碼:
(*(void(*)())0)();

??????????????????????????????????????????????????????????????????????????????????????

在剛看到這段代碼時(shí)我的心情如上👆。心想:“魔法,這一定是魔法”。但其實(shí)冷靜思考過(guò)后,最終還是理解了這一段離譜且詭異的代碼:

首先從最里開(kāi)始,void(*)? (),這樣單獨(dú)拆開(kāi)后我們不難發(fā)現(xiàn),這是一個(gè)函數(shù)指針類型,只不過(guò)是一個(gè)void型的函數(shù)且不用傳參,在這整體上再套多一個(gè)小括號(hào)并在后面加上數(shù)字0,變?yōu)?void(*)?()?)0的樣子,這里最外一層的小括號(hào)其實(shí)是強(qiáng)制類型轉(zhuǎn)換符,將0這個(gè)地址上放入一個(gè)函數(shù)指針(也就是放了一個(gè)函數(shù))。而最終變?yōu)椋?(void(*)())0)(),其實(shí)是調(diào)用了0地址上的這個(gè)參數(shù)為無(wú)參,返回類型是void的函數(shù)。所以總結(jié)來(lái)說(shuō),整個(gè)代碼是在調(diào)用0地址處的函數(shù)

但是?。。。?/p>

當(dāng)我們將上面代碼在編譯器中正式運(yùn)行時(shí)是不可能的,會(huì)出現(xiàn)運(yùn)行中止或報(bào)錯(cuò)或根本不運(yùn)行。這是因?yàn)榈刂?是我們普通用戶禁止被使用的地址,我們是無(wú)法使用的,因?yàn)?地址是開(kāi)機(jī)啟動(dòng)時(shí)才訪問(wèn)的地址。

再來(lái)看一條簡(jiǎn)單一點(diǎn)的代碼(可能)

void (*signal(int,void(*)(int)))(int);

上面代碼要這么看:void(* signal(int,void(*)(int)) )(int);

這樣子就不難看出(應(yīng)該不難)signal(int,void(*)(int))是一個(gè)函數(shù)的聲明,因?yàn)楹瘮?shù)的參數(shù)位置如果是調(diào)用的話,則不應(yīng)該為類型,所以這個(gè)是函數(shù)的聲明,這是一個(gè)函數(shù)名為signal,參數(shù)為int型和函數(shù)指針型的函數(shù),函數(shù)名有了,參數(shù)也有了,現(xiàn)在缺少的就是返回類型,這個(gè)返回的類型便是剩下的→void ( *)(int)。

Tip:在這里要特別注意,*總是要和名字在一起,不可以寫(xiě)為void (?*)(int) signal(int,void(*)(int))的形式

看吧,不難吧(后仰攤手)

什么??還是難???那好吧,下面我們嘗試著簡(jiǎn)化一下這樣的代碼(其實(shí)我也覺(jué)得難)

將void(*)(int)這樣類型的函數(shù)指針類型重命名為pfun_t,這里要用到typedef,但注意?。〔皇菍?xiě)為這樣:typedef void(* )(int) pfun_t。而是要寫(xiě)為:typedef void(* pfun_t)(int) 這里這么寫(xiě)是因?yàn)?總要與名字在一起(上面tip里有說(shuō)過(guò))。

經(jīng)過(guò)函數(shù)指針的重命名后,上面的代碼可以最終簡(jiǎn)化為:

pfun_t signal(int,pfun_t);


函數(shù)指針數(shù)組

按照字面意思,我們可以知道,這是一組存放函數(shù)指針類型元素的數(shù)組。

函數(shù)指針數(shù)組的使用:

#includeint Add(int x, int y)
{
  return x + y;
}
int Sub(int x, int y)
{
  return x - y;
}
int Mul(int x, int y)
{
  return x * y;
}
int Div(int x, int y)
{
  return x / y;
}
int main()
{
  int (*arr[5])(int, int) = { Add,Sub,Mul,Div };
  int i = 0;
  for (i = 0; i< 5; i++)
  {
    printf("%d\n",arr[i](8, 4));
  }
  return 0;
}

函數(shù)指針真正用處用法

函數(shù)指針可以利用寫(xiě)一個(gè)函數(shù),使其形參的類型為函數(shù)指針類型,從而達(dá)到一個(gè)函數(shù)可以調(diào)用多個(gè)不同函數(shù)的一個(gè)函數(shù)。

我們先寫(xiě)下下面這樣的一段代碼:

#includevoid Menu()
{
  printf("******************************\n");
  printf("****  1.Add      2.Sub    ****\n");
  printf("****  3.Mul 4.Div 0.exit  ****\n");
  printf("******************************\n");
}

int Add(int x, int y)
{
  return x + y;
}

int Sub(int x, int y)
{
  return x - y;
}

int Mul(int x, int y)
{
  return x * y;
}

int Div(int x, int y)
{
  return x / y;
}

int main()
{
  int input = 0;
  do
  {
    int x = 0;
    int y = 0;
    Menu();
    printf("請(qǐng)輸入你要的操作");
    scanf("%d", &input);
    switch (input)
    {
      case 0:
        printf("結(jié)束操作\n");
        break;
      case 1:
        printf("請(qǐng)輸入你想要操作的兩個(gè)數(shù):");
        scanf("%d %d", &x, &y);
        printf("%d\n", Add(x, y));
        break;
      case 2:
        printf("請(qǐng)輸入你想要操作的兩個(gè)數(shù):");
        scanf("%d %d", &x, &y);
        printf("%d\n", Sub(x, y));
        break;
      case 3:
        printf("請(qǐng)輸入你想要操作的兩個(gè)數(shù):");
        scanf("%d %d", &x, &y);
        printf("%d\n", Mul(x, y));
        break;
      case 4:
        printf("請(qǐng)輸入你想要操作的兩個(gè)數(shù):");
        scanf("%d %d", &x, &y);
        printf("%d\n", Div(x, y));
        break;
      default:
        printf("輸入錯(cuò)誤,請(qǐng)重新輸入");
        break;
    }
  } while (input);
}

在上面我們會(huì)發(fā)現(xiàn)case1,2,3,4大量代碼是重復(fù)冗余的,且Add,Sub,Mul,Div函數(shù)都是返回的int型,且都有兩個(gè)int型的參數(shù),對(duì)于這種情況,我們可以利用寫(xiě)一個(gè)函數(shù),來(lái)調(diào)用這些形式上差不多相同的函數(shù),能夠做到縮減代碼量的目的,而調(diào)用這些函數(shù)以形參形式傳過(guò)去,就需要用到函數(shù)指針類型。

在這里我們創(chuàng)建一個(gè)Cal函數(shù),其參數(shù)形式為函數(shù)指針型,若以上面函數(shù)來(lái)舉例,則寫(xiě)出如下代碼:

void Cal(int (*fun)(int,int))
{}

然后再將重復(fù)的代碼放入Cal函數(shù)內(nèi)之后刪去,便可以達(dá)到減少重復(fù)代碼的目的了。下面是完整的更改后的代碼:

#includevoid Menu()
{
  printf("******************************\n");
  printf("****  1.Add      2.Sub    ****\n");
  printf("****  3.Mul 4.Div 0.exit  ****\n");
  printf("******************************\n");
}

int Add(int x, int y)
{
  return x + y;
}

int Sub(int x, int y)
{
  return x - y;
}

int Mul(int x, int y)
{
  return x * y;
}

int Div(int x, int y)
{
  return x / y;
}

void Cal(int (*fun)(int, int))
{
  int x = 0;
  int y = 0;
  printf("請(qǐng)輸入你想要操作的兩個(gè)數(shù):");
  scanf("%d %d", &x, &y);
  printf("%d\n", fun(x, y));
}

int main()
{
  int input = 0;
  do
  {
    Menu();
    printf("請(qǐng)輸入你要的操作");
    scanf("%d", &input);
    switch (input)
    {
    case 0:
      printf("結(jié)束操作\n");
      break;
    case 1:
      Cal(Add);
      break;
    case 2:
      Cal(Sub);
      break;
    case 3:
      Cal(Mul);
      break;
    case 4:
      Cal(Div);
      break;
    default:
      printf("輸入錯(cuò)誤,請(qǐng)重新輸入");
      break;
    }
  } while (input);
}

看起來(lái)比上一種寫(xiě)法干凈整潔了許多。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前名稱:C語(yǔ)言中多種指針相關(guān)類型詳解-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://m.2m8n56k.cn/article10/cciido.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣、網(wǎng)站設(shè)計(jì)公司靜態(tài)網(wǎng)站ChatGPT、微信公眾號(hào)、網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司
主站蜘蛛池模板: 日韩99在线| 欧美片能看的一级毛片 | 亚洲日本欧美综合在线一 | 黄色三级网 | 久草在现视频 | 男女午夜视频 | 114毛片免费观看网站 | 巨大热杵在腿间进进出出视频 | 美毛片 | 亚洲视频一区二区在线观看 | 日韩亚洲成a人片在线观看 日韩亚洲精品不卡在线 | 亚洲精品美女国产一区 | 在线一区二区观看 | 一级aaaaa毛片免费视频 | 天天夜天干天天爽 | 久爱综合 | 亚洲欧洲eeea在线观看 | 欧美一级免费在线观看 | 亚洲三级一区 | 香港经典a毛片免费观看看 香港经典a毛片免费观看爽爽影院 | 国产成人一区二区视频在线观看 | 国产精品久久久久久久福利院 | 夜色邦合成福利网站 | 日韩午夜免费视频 | 九月婷婷亚洲综合在线 | 成人综合在线视频免费观看 | 亚洲 欧美 精品专区 极品 | 国产亚洲一区二区三区在线 | 国产成人精品福利网站在线 | 亚洲国产99 | 美国毛片一级视频在线aa | 一级毛片黄片 | 久久久久久极精品久久久 | 成人综合婷婷国产精品久久免费 | 日韩精品亚洲专区在线观看 | 日本aaa视频| 国产精品爱久久久久久久 | 92看片淫黄大片一级 | 99视频在线观看视频 | 日韩欧美综合在线二区三区 | av在线手机播放 |