C指標介紹

2021-09-26 16:00:57 字數 4182 閱讀 6167

參考: 舉例

int p;//整型變數

int *p;//整型型別的指標

int *p[3];//整型型別的指標陣列

int (*p)[3];//指向整型陣列的指標

int **p;//指向整型指標的指標

int p(int);//函式,入參是整型數,返回值是整型數

int (*p)(int);//函式指標,指向函式的指標,入參是整型,返回值是整型

int *(*p(int))[3];//函式,入參是整型數,返回值是指標,指標指向乙個陣列,陣列元素是整型指標

指標概念

指標是乙個特殊的變數,裡面儲存的值時記憶體裡的乙個位址

指標的型別:指標本身所具有的型別

指標所指向的型別:決定了編譯器將把那片記憶體區里的內容當做什麼來看待

指標本身佔據的記憶體區:sizeof可以測得,如32位平台裡,指標本身佔據4位元組。此概念在判斷乙個指標表示式是否是左值時很有用。

指標的型別

將指標宣告語句中的指標名字去掉,剩下的就是指標本身具有的型別

int* ptr;//指標型別是int*

char *ptr;//指標型別是char*

int **ptr;//指標型別是int**

int(*ptr)[3];//指標型別是int(*)[3]

int*(*ptr)[4];//指標型別是int*(*)[4]

指標所指向的型別

將指標宣告語句中的指標名字和名字左邊的指標宣告符*去掉,剩下的就是指標所指向的型別

int *ptr;//指標所指向的型別是int

char *ptr;//char

int **ptr;//int *

int(*ptr)[3];//int()[3]

int(*(*ptr)[4]);//int*()[4]

指標的值

指標的值是xx,相當於說該指標指向了以xx為首位址的一片記憶體區域。

指標本身所佔據的記憶體區

在32位程式裡,所有型別的指標的值都是乙個32位整數,因為32位程式裡記憶體位址全都是32位長,因此指標本身佔據4個位元組的長。

指標的算術運算

char a[20];

int *ptr = (int *)a;

ptr++;

指標ptr+1,編譯器將指標ptr的值加上了sizeof(int),32位程式中,int佔4位元組,因此ptr指向的位址是a位址向高位址方向增加了4位元組,由於char型別長度為1位元組,因此ptr指向陣列a中的第四個元素

#include

int main()

char a[20] = "you_are_a_girl";

char *p = a;

char **ptr = &p;

printf("**ptr = %c\n", *ptr);

ptr++;

printf("**ptr = %c\n", **ptr);

ptr的型別是char**,指向的型別是char*型別,此處指標的值是p的位址,當執行ptr++時,會使指標的值加乙個sizeof(char*),即&p+4,那麼*(&p + 4)指向**?誰也不知道,可能是乙個隨機值,也可能是乙個非法操作。

總結:指標加(減)乙個整數

指標ptrold加(減)乙個整數n後,結果是乙個新的指標ptrnew,ptrnew的型別與ptrold的型別相同,ptrnew所指向的型別和ptrold所指向的型別也相同。ptrnew的值將比ptrold的值增加(減少)了n乘sizeof(ptrold所指向的型別)個位元組。也就是說,ptrnew所指向的記憶體區將比ptrold所指向的記憶體區高(低)位址方向移動了n乘sizeof(ptrold所指向的型別)個位元組。

指標加(減)乙個指標

兩個指標不能進行加法運算,這是非法操作,因為進行加法操作後,得到的結果指向乙個不知所向的地方,毫無意義。

兩個指標可以進行減法操作,但必須型別相同,一般用在陣列方面。

運算子&和*

&是取位址運算子,*是間接運算子

&a的運算結果是乙個指標,指標的型別是a的型別加*,指標所指向的型別是a的型別,指標所指向的位址是a的位址。

*p的運算結果是p所指向的東西,它的型別是p指向的型別,它所占用的位址是p所指向的位址。

int a = 12; int b; int *p; int **ptr;

p = &a;//&a的結果是乙個指標,型別是int*,指向的型別是int,指向的位址是a的位址

*p = 24;//*p的型別是int,所占用的位址是p所指向的位址,*p就是變數a

ptr = &p;//&p的結果是個指標,該指標的型別是p的型別加個*,在這裡是int**。該指標所指向的型別是p的型別,這裡是int*,該指標所指向的位址就是指標p自己的位址。

*ptr = &b;//*ptr是個指標,&b的結果也是個指標,且這兩個指標的型別和所指向的型別是一樣的,因此用&b來給*ptr賦值是沒問題的。

**ptr = 34;//*ptr的結果是ptr所指向的東西,在這裡是乙個指標,對這個指標再做一次*運算,結果是乙個int型別的變數。

指標表示式

乙個表示式的結果如果是乙個指標,那麼這個表示式就叫指標表示式

int a,b;

int array[10];

int *pa;

pa = &a;//&a 是乙個指標表示式。

int **ptr = &pa;//&pa 也是乙個指標表示式。

*ptr = &b;//*ptr 和&b 都是指標表示式。

pa = array;

pa++;//這也是指標表示式。  

char *arr[20];

char **parr = arr;//如果把arr 看作指標的話,arr 也是指標表示式 

char *str;

str = *parr;//*parr 是指標表示式  

str = *(parr + 1);//*(parr+1)是指標表示式  

str = *(parr + 2);//*(parr+2)是指標表示式  

當乙個指標表示式的結果指標已經明確地具有了指標自身佔據的記憶體的話,這個指標表示式就是乙個左值,否則就不是乙個左值。

&a不是左值,因為它還沒有佔據明確的記憶體。*ptr是乙個左值,因為*ptr 這個指標已經佔據了記憶體,其實*ptr 就是指標pa,既然pa 已經在記憶體中有了自己的位置,那麼*ptr 當然也有了自己的位置。

char *str[3] = ;  //宣告了結構物件ss,並把ss 的成員初始化為20,30 和40。  

structmystruct *ptr=&ss;  //宣告了乙個指向結構物件ss 的指標。它的型別是  mystruct *,它指向的型別是mystruct。  

int*pstr=(int*)&ss;  //宣告了乙個指向結構物件ss 的指標。但是pstr 和 它被指向的型別ptr 是不同的。  

通過指標ptr 來訪問ss 的三個成員變數

ptr->a; //指向運算子,或者可以這們(*ptr).a,建議使用前者

ptr->b;

ptr->c;

通過指標pstr 來訪問ss 的三個成員變數

*pstr; //訪問了ss 的成員a。

*(pstr+1); //訪問了ss 的成員b。

*(pstr+2) //訪問了ss 的成員c。

指標和函式

int fun1(char *, int);

int (*pfun1)(char *, int);//函式指標

pfun1 = fun1;

int a = (*pfun1)("abcdefg", 7);//通過函式指標呼叫函式

指標型別轉換

floatf=12.3;  

float*fptr=&f;  

int*p;  

p = (int*)&f;

如果有乙個指標f,我們需要把它的型別和所指向的型別改為tyep *type, 那麼語法格式是: (type *)f;這樣強制型別轉換的結果是乙個新指標,該新指標的型別是type *,它指向的型別是type,它指向的位址就是原指標指向的位址。而原來的指標f 的一切屬性都沒有被修改。

乙個函式如果使用了指標作為形參,那麼在函式呼叫語句的實參和形參的結合過程中,必須保證型別一致,否則需要強制轉換.

C語言 指標介紹

本文只是簡單的介紹了指標的一些概念,如果想更詳細的了解指標的知識點可以 我的另外兩篇部落格。指標基礎 指標高階 表示一些複雜的資料結構 快速傳遞資料 使函式返回乙個以上的值 直接訪問硬體 能方便處理字串 是理解物件導向語言中引用的基礎 總結 指標是c語言的靈魂 指標是乙個變數,用來存放位址的變數。記...

C 指標作為函式引數介紹

void getptr int p,int num void main 我們想通過以上 來為ptr分配記憶體,結果如何呢,大家可以試一下,肯定是失敗的。同樣還有下面一段 來實現上面所述功能。void getptr int p,int num void main 第2段 可以實現為ptr動態分配記憶體...

關於C 指標很好的介紹

通過指向類的null指標呼叫類的成員函式 試圖用乙個null指標呼叫類的成員函式,導致崩潰 include using namespace std class a void set int x intget const int main 為什麼會這樣?通過非法指標呼叫函式,就相當於給函式傳遞了乙個指...