函式 陣列 指標(2)

2021-10-02 09:39:33 字數 4551 閱讀 4549

內容與task[2] 提高部分相關

指標能夠有效的處理陣列!(是否學好c語言的重要標準就是指標與檔案)

先直接給題目:

理解並寫出結果:

1、

#include 

int main();

char** cp=

; char*** cpp =cp;

printf(

"%s\n", **++cpp)

; //列印句1

printf(

"%s\n", *--*++cpp + 3)

; //列印句2

printf(

"%s\n", *cpp[-2] + 3)

; //列印句3

printf(

"%s\n", cpp[-1]

[-1] + 1)

; //列印句4

system(

"pause");

return 0;

}

陣列中,變相使用指標的例子:陣列名是陣列首元素的位址,

即ar==&ar [0]

注意:ar和&ar[0] 都表示陣列首元素的記憶體位址,兩者都是常量,不會被修改。但是可以把他們賦給指標變數,可以修改指標變數的值

在c中指標+1指的是增加乙個儲存單元(遞增它所指向型別的大小)

date+2==&date[2]

*(date+2)==date[2]

注意運算子的優先順序,即 * 的優先順序高於 +

(傳送門:運算子的優先順序)(網上有好多的

*(date+2)指的是date[2]的值

*date +2指的是date[0]的值 +2

對於乙個較大物件的位址,指標的值通常是該物件第乙個位元組的位址

關於指標的運算子優先順序問題

一元運算子*和自加++ 優先順序相同,結合規律為從右往左

%s只有遇到\0時才會停止

對題目進行解釋:

char *c=

;

這裡定義了乙個字串陣列(以指標形式定義) c[0] - c[3]

char** cp=

;

定義二級指標陣列 :

cp[0]指向c+3即」first」

cp[1]指向c+2即』』point」,以此類推

char*** cpp =

cp;

cpp指向cp[0]

下面是重點理解部分:

printf(

"%s\n", **++cpp)

先將指標cpp指的位置自加遞增,即cp[1] ,再解引兩次

即最終指向c+2 」point」

printf(

"%s\n", *--*++cpp + 3)

;

①上乙個操作使得cpp指向cp[1],自加後指向cp[2]

此時++cpp為cp[2]的位址,解引後為c+1的位址

②再自減,注意不是cpp自減 是c+1的位址自減 即指向c

也就是*–*++cpp為」enter」字串

③最後的+3:

因為這個字串是指標形式,所以+3是從第三個字母開始的

+3的操作等價於在這個字元陣列的首位址的基礎上再右移三個位址,指向了第二個e, %s列印剩餘的所有

printf(

"%s\n", *cpp[-2] + 3)

;

此時cpp[-2]指向cp[0] 即c[3],

相當於指向了乙個字元陣列的首位址。

+3的操作等價於在這個字元陣列的首位址的基礎上再右移三個位址,指向了s

然後通過printf將s和之後的所有剩餘字元全部列印。

printf(

"%s\n", cpp[-1]

[-1] + 1)

;

這是用陣列表示法表示指標,開頭說的

cpp[-1]為cp[1] (c+1) (我想不來 哭了)

執行結果:

point

erst

ew

2.

#include

struct test

*p;int

main()

指標的相關運算

指標與整數相加或相減(+n):

指標增加n個單元,單元的大小與指標所指的型別相同

指標的遞增遞減:指標的位置進行移動

指標求差:通常求的是同乙個陣列內的不同元素之間的距離

注意差值的單位不是位元組,舉例:int *p1- int *p2=2表示 p1 p2相隔兩個int

指標的比較:兩個指標所指型別必須相同

這個在比較兩個字串的時候常用到

重點:指標與整數的加減法公式為 p = p +/- sizeof(type * p)

因為我們用sizeof得到的結構體test的長度為32,所以在第二個printf中,p+0x1的值為0x100000+sizeof(test)*0x1=0x100020。

而(unsigned

long)將指標變數p強制轉化為無符號整型常量,所以第三個printf函式中的表示式實質上是乙個無符號長整形數加上另乙個整數,得到0x100001。

同理,(unsigned

int*)將指標變數p強制轉化為無符號整型指標,所以最後乙個printf函式中的表示式值為0x100000+sizeof(unsigned

int*)*0x1=0x100004。

結果就是這樣

3.

#include

intmain()

;int

* ptr1 =

(int*)

(&a +1)

;int

* ptr2 =

(int*)

((int)a +1)

;printf

("%x\n%x\n"

, ptr1[-1

],* ptr2)

;\\輸出4

2000000

return0;

}

結果:

0x4

0x2000000

以下內容摘自大佬cyf -> 傳送門

解釋 :

首先,&a指的是取陣列a的位址,而&a + 1指的是加上乙個int a[4]的長度,即sizeof(int) * 4=16位元組,所以ptr1指向陣列a後面的記憶體單元,如果用下標表示就是a[5]

由指標與整數的加減法公式p = p +/- sizeof(type * p), ptr1[-1]表示ptr1指向的位址再減去sizeof(int* ),即指向a[4],所以第乙個%x輸出對應的是0x4.

(int)a+1的值就是元素a[0]的第二個位元組的位址,然後把這個位址強制轉化為(int)型別賦給ptr2,也就是說ptr2的值應該為元素a[0]的第二個位元組開始的連續4個byte的內容。

不過要想理解為什麼輸出了2000000,就要首先明白數字在陣列中是怎麼被儲存的:

每個元素具體儲存方式,取決於cpu。 有兩種:

1、小端(little endian): 將低序位元組儲存在起始位址(低位編址), 位址低位儲存值的低位,位址高位儲存值的高位 。 目前大多數cpu是按照這種方式儲存的,包括intel和移動端最常見的arm。 比如4位元組整型值為0x12345678的情況,那麼在記憶體中會儲存為: 0x78 0x56 0x34 0x12

2、大端(big endian): 與小端相反, 將高序位元組儲存在起始位址(高位編址),位址低位儲存值的高位,位址高位儲存值的低位。 之前的例子在大端情況下儲存為: 0x12 0x34 0x56 0x78

因此,a[0]在記憶體中被儲存為0x01 0x00 0x00 0x00,a[1]在記憶體中被儲存為0x02 0x00 0x00 0x00,此時ptr2所指向的記憶體區域的值就是0x00 0x00 0x00 0x02

但是,在printf進行輸出時,記憶體中的值是自右而左地被讀出的,因此輸出的值應該是0x02000000

有乙個誤區(可能只有我才會犯)

錯誤的認為只有定義了指標之後才能用指標表示法表示陣列

實際上陣列表示法和指標表示法都可以使用

(指標表示法就是用陣列名+n 以及*訪問值 來實現對陣列的使用)

兩種方法怎麼方便怎麼來【在函式中】

函式陣列和指標(編寫乙個處理陣列的函式

關於函式的形參: 在函式宣告和定義時

允許:int * ar = = int ar[ ]

int * = = int [ ] // 省略變數名稱的形式

指標 函式 陣列

1.指標函式 指標函式就是返回指標值的函式,本質是乙個函式。所以指標函式等價於 返回值為指標的函式 宣告形式 type func 引數列表 2.函式指標 函式指標就是乙個指向函式的指標。每個函式在編譯時,會被分配乙個入口位址,一般用函式名來表示,這個位址就是該函式的指標。宣告形式 type func...

函式指標,指標函式,陣列指標,指標陣列 區分

what why how 這些怎麼區分 函式指標 重點在指標,表示它是乙個指標,它指向的是乙個函式。eg int fun 指標函式 重點在函式,表示它是乙個函式,它的返回值是指標。eg int fun 陣列指標 重點在指標,表示它是乙個指標,它指向的是乙個陣列。int fun 8 指標陣列 重點在陣...

函式指標和指標函式 陣列指標和指標陣列

函式指標 在程式執行中,函式 是程式的演算法指令部分,它們和陣列一樣也占用儲存空間,都有相應的位址。可以使用指標變數指向陣列的首位址,也可以使用指標變數指向函式 的首位址,指向函式 首位址的指標變數稱為函式指標。1 函式指標定義 函式型別 指標變數名 形參列表 函式型別 說明函式的返回型別,由於 的...