日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言程序设计 | 指针的进阶(一):字符指针、数组指针、指针数组、函数指针

發布時間:2024/4/11 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言程序设计 | 指针的进阶(一):字符指针、数组指针、指针数组、函数指针 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

指針的進階(一)目錄:

  • 字符指針
  • 數組指針和指針數組
  • 函數指針

字符指針

在開始講解這一章節之前,我們需要了解指針前面聲明的類型的意義

類型 * 指針名

對于指針來說,我們在給指針進行聲明時,我們聲明的類型并不是指針的類型,而是指針所指向的地址的類型,也就是指針看待這段地址的方式,它該如何讀取數據,它如果加一該移動多少位,只有了解了這個才能方便理解下面的內容

我們首先來說的就是字符指針char*

一般我們是這樣運用字符指針的

char a = 'a';char* p = &a;

但是我們還能以這種方式運用

char*str = "hello world";

這時候,經常就會有初學者以為我們的指針指向的是hello world這個字符串,但其實這里只是把字符串的首元素的地址保存到了這個指針當中。

同時我們還需要理解這樣的指針與字符串的區別。

例如:

char str1[] = "hello";char *str2 = "world";

這里的str1是在棧上開辟一塊內存空間來存放hello這段字符,而這里的str2是用指針指向常量區的‘’world‘’這段字符,所以我們無法給str2進行賦值與修改,因為常量是不可改變的,我們也無法將這str1與str2進行比較,因為他們是本質不同的兩樣東西。
借此,在引申一個小內容

#include<stdio.h> int main() {char str1[] = "helloworld.";char str2[] = "helloworld.";char* str3 = "helloworld.";char* str4 = "helloworld.";if(str1 == str2)printf("1\n");elseprintf("0\n"); if(str3 == str4)printf("1\n");elseprintf("0\n"); return 0; }


為什么在這里,str1與str2不同呢?
因為我們給字符串賦值時,是在棧上面開辟一個內存空間,來給這個字符串存放一個數值,雖然他們存放的內容是一樣的,但是它們存放在不同的內存塊中,所以進行比較的時候是不同的
那為什么str3和str4是相同的呢?
因為它們是字符指針,它們指向的都是常量區中的hello world這段字符,它們指向的內容一樣,所以它們相同。
這也就是為什么我們在進行字符串的比較的時候運用的都是strcmp這個函數的原因。


數組指針和指針數組

在我剛剛接觸指針的時候,我經常會搞混兩個東西,一個是數組指針,一個是指針數組,因為它們太過相似,但如果你了解了運算符的優先級以及我之前說的指針如何看待類型,你就會很快的區分它們

上圖中的兩個指針是不是特別相似?那我們如何區分呢?

首先,我們先看幾個運算符的優先級對于p1,[] 的優先級是很明顯高于 *的,所以它的本質就應該是一個數組,而剩下的int *就應該是它所存放的數據類型,所以它是一個存放指針元素的數組,即指針數組。
而對于p2,它的()的優先級是很明顯高于 [] 的,所以我們應該先去考慮括號中的內容,括號中是一個指針 *,所以它的本質就應該是一個指針,而剩下的就是它所指向的地址的類型,所以它是一個指向數組的指針,即數組指針。

如果我們要了解一個數組指針是如何作用的,我們首先要了解這樣一個知識點。

對于一個數組,它的數組名和&數組名有什么區別。
我們都知道數組名是這個數組的首元素的地址,但是&數組名卻不是很了解。

int main() {int arr[10] = {0};printf("%p",arr);printf("%p",&arr);return 0; }


我們查看它們的地址,卻完全的一樣,那是不是證明它們相同呢?

int main() {int arr[10] = {0};printf("%p",arr+1);printf("%p",&arr+1);return 0; }

其實不是,我們再給它們分別+1

這里區別就顯現出來了,arr+1加的只是一個元素的大小,而&arr+1加了一整個數組的大小。
所以我們就能了解,&arr指向的是這一整個數組的地址。
而我們的數組指針,是一個指向數組地址的指針,所以數組指針應該這樣指向一個數組。

int (*p)[10] = &arr;

函數指針

在了解函數指針前我們要先了解一個小的誤區


這兩個哪一個才是函數指針呢?
還是之前判斷數組指針的那個方法,我們看優先級,先看括號,它是一個指針,剩下的就是它所指向的類型,一個返回值為void的函數。
而第二個其實就是一個函數的聲明,聲明一個返回值為void*的函數

我們該如何調用這個函數指針呢?

無論是直接調用還是進行解引用后調用,我們都可以直接使用這個函數

#include<stdio.h>void print() {printf("1\n"); }int main() {void (*p)();p = print;p();(*p)();return 0; }


在使用函數指針的時候,因為函數的特殊性,在很多情況下代碼的可讀性會十分差,如下面這段代碼。

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



這是它的參數類型

這是它的函數名
外面剩下的則是它的返回類型。
所以它是一個參數為int 和函數指針的一個函數,返回值為函數指針。
這樣的代碼讓人很難理解。
那該如何簡化呢?我們可以用typedef進行簡化

typedef void(*p)();

簡化完后

這樣我們的代碼可讀性就大大的提升了。

第一部分就講到這里吧

總結

以上是生活随笔為你收集整理的C语言程序设计 | 指针的进阶(一):字符指针、数组指针、指针数组、函数指针的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。