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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

c语言指针的相关运算,C语言指针的运算

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言指针的相关运算,C语言指针的运算 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文討論使用指針進行的運算,最重要的運算是獲取指針所引用的對象或函數。也可以比較指針,使用指針來遍歷一個內存區域。

使用指針讀取與修改對象

間接運算符 * 生成內存中的位置,該位置的地址存儲在一個指針中。如果 ptr 是一個指針,那么 *ptr 就是 ptr 所指向的對象(或函數)。

使用間接運算符有時候被稱為解引用(dereferencing)一個指針。指針指向的內存位置被認為存儲有一個對象,指針的類型決定了該對象的類型。例如,當用 int 指針獲取一個特定內存位置,讀出或寫入的也是 int 類型的對象。

與乘法運算符 * 不同,間接運算符 * 是一元運算符,也就是說,間接運算符只有一個操作數。在例 1 中,ptr 指向變量 x。因此,表達式 *ptr 等效于變量 x 本身。

【例1】解引用一個指針double x, y, *ptr; // 兩個double變量和一個double指針 ptr = &x; // 使得ptr指向x *ptr = 7.8; // 對變量x賦值7.8 *ptr *= 2.5; // 將x乘以2.5 y = *ptr + 0.5; // 將加法x+0.5的結果賦值給y

不要混淆指針聲明中的星號(*)和間接運算符。聲明中的語法可以被視為展示了如何使用指針。如下例所示:double *ptr;

如上述聲明,ptr 具有 double* 類型(讀為:“指向double的指針”)。因此,表達式 *ptr 類型是 double。

當然,間接運算符 * 必須匹配一個具有有效地址的指針。這個用法要求在編寫程序時需要特別小心!例 1 中,如果沒有 ptr=&x 為 ptr 分配有效地址,那么所有包含 *ptr 的語句都是沒有意義的(解引用一個沒有定義的指針),有可能會造成程序崩潰。

一個指針變量,其本身也是內存中的一個對象,也就是說,其他指針可以指向該指針。若想創建指針的指針,必須使用兩個星號,如下例所示:char c = 'A', *cPtr = &c, **cPtrPtr = &cPtr;

表達式 *cPtrPtr 當前生成 char 指針 cPtr,而 **cPtrPtr 的值是 char 變量 c。圖 1 展示了這樣的關系。

圖1

指針的指針不僅限于兩個層次的間接運算。也可以根據自己的需要定義多個層次的間接運算。然而,不能通過多次使用地址運算符 & 來取得指針的值:char c = 'A', **cPtrPtr = &(&c); // 錯誤!

上例中的第二個初始化語句是非法的:表達式(&c)不可以作為 & 的操作數,因為它不是一個左值。換句話說,在本例中,不存在可以讓 cPtrPtr 指向的 char 指針。

如果將一個指針采用引用方式傳入函數,以讓函數可以修改該指針的值,那么該函數的參數就是指針的指針。下面簡單的例子是一個函數,動態地創建一個新的記錄,將其地址存儲在一個指針變量中:#include // 記錄的類型: typedef struct { long key; /* ... */ } Record; _Bool newRecord( Record **ppRecord ) { *ppRecord = malloc( sizeof(Record) ); if ( *ppRecord != NULL ) { /* ...初始化新記錄的成員... */ return 1; } else return 0; }

下列語句是調用函數 newRecord()的一種可能方式:Record *pRecord = NULL; if ( newRecord( &pRecord) ) { /* ...pRecord現在指向了一個新的Record對象... */ }

表達式 *pRecord 生成新的記錄,并且(*pRecord).key 是該記錄中的 key 成員。表達式(*pRecord).key 中的括號是有必要的,因為點運算符(.)比間接運算符(*)具有更高的優先級。

不用上面運算符與括號結合的方式,也可以使用箭頭運算符 -> 來獲取結構或聯合的成員。如果 p 是一個指向結構或聯合的指針,并且該結構或聯合具有成員 m,那么表達式 p->m 等效于(*P).m。因此,下面的語句將一個值賦值給 pRecord 所指的 key 成員:pRecord->key = 123456L;

修改和比較指針

除了使用賦值操作讓一個指針引用一個給定的對象或函數,也可以使用算術運算來修改一個對象指針。當進行指針算術運算(pointer arithmetic)時,編譯器會自動在運算中采用指針所指類型的空間大小。

對于指向對象的指針,可以進行下列的運算:

(1) 對一個指針執行整數加法和減法操作。

(2) 兩個指針相減。

(3) 比較兩個指針。

當將兩個指針相減時,這兩個指針必須具有相同的基本類型,但是類型限定符則不需要一樣。而且,可以使用相等運算符(==和!=)來將任何指針與空指針常量比較,也可以將對象指針與 void 指針比較。

這里所描述的三種指針運算,通常只針對指向數組元素的指針時才有用。為了展示這些運算的作用,假設有兩個指針 p1 和 p2,它們都指向數組 a 內的元素:

(1) 如果 p1 指向數組元素 a[i],并且 n 是一個整數,那么表達式 p2=p1+n 的使得 p2 指向數組元素 a[i+n](假設 i+n 仍在數組 a 的索引范圍內)。

(2) 減法 p2-p1 的結果是獲得兩個指針之間數組元素的數量,結果的類型是 ptrdiff_t。該類型定義在頭文件 stddef.h 中,通常定義成 int。在賦值運算 p2=p1+n 之后,表達式 p2-p1 的值是 n。

(3) 如果 p2 所引用的元素比 p1 所引用的元素具有更大的索引值,則 p1

因為一個數組的名稱會隱式地轉換為指向數組第一個元素的指針,所以可以把數組的下標表示法替換為指針算術:

(1) 表達式 a+i 是指向 a[i] 的指針,而 *(a+i)的值是元素 a[i]。

(2) 表達式 p1-a 的結果是 p1 指向元素的索引值 i。

在例 2 中,函數 selection_sortf()對 float 元素數組進行排序,使用選擇性排序算法。這個函數使用指針而非索引完成對 float 元素數組的排序,函數swapf()維持不變。

【例2】指針版本的函數 selection_sortf()// 函數swapf()交換兩個float變量的值 // 參數:兩個指向float的指針 inline void swapf( float *p1, float *p2 ) { float tmp = *p1; *p1 = *p2; *p2 = tmp; // 交換*p1和*p2 } // 函數selection_sortf()使用選擇性排序算法,對float元素數組排序 // 參數:一個float元素數組,以及它的長度 void selection_sortf( float a[], int n ) // 對有n個float元素的數組a進行排序 { if ( n <= 1 ) return; // 不進行排序 register float *last = a + n-1, // 指向最后一個元素的指針 *p, // 指向一個選定元素的指針 *minPtr; // 指向當前最小值元素的指針 for ( ; a < last; ++a ) // 將指針遍歷整個數組 { minPtr = a; // 在a所指的元素與最后一個元素之間 for ( p = a+1; p <= last; ++p ) // 找到最小值元素 if ( *p < *minPtr ) minPtr = p; swapf( a, minPtr ); // 將最小值元素與a所指的元素交換 } }

通常來講,指針版本的函數比使用索引版本的函數具有更高效率,因為使用索引 i 獲取數組 a 的元素,表達式為 a[i] 或 *(a+i),它涉及將 a 的地址加上 i*sizeof(元素類型)的值,以獲得對應的數組元素地址。指針版本相比之下需要的運算就少得多了,因為指針本身可遞增,不需要索引,并且指針直接指向所需的元素。原文始發于:C語言指針的運算

總結

以上是生活随笔為你收集整理的c语言指针的相关运算,C语言指针的运算的全部內容,希望文章能夠幫你解決所遇到的問題。

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