2019-04-01 C初階4:指針

1. 指針運算

1.1 算術運算

  • 加減+草慧、-
    指針與整數(shù)相加:表示指針指向下個變量。
    指針與整數(shù)相減:表示指針指向上個變量高镐。
    指針與指針相減:兩個指針的元素間隔個數(shù)。
int arr[]={100,101,102,103,104,105};
int* p = arr;
int* q;
for(int i=0;i<5;++i){
    q = p+i;
    printf("%d\n",*q);
}
for(int i=0;i<5;++i){
    p = q-i;
    printf("%d\n",*p);
}
printf("q-p=%d\n",q-p);

  • 自增自減++脾拆、--

指針能夠算術運算嫉髓,必然能夠自增自減混稽。

int arr[]={100,101,102,103,104,105};
int* p = arr;
for(int i=0;i<5;++i){
    printf("%d\n",*p++);
}
for(int i=0;i<5;++i){
    printf("%d\n",*p--);
}

*p++/*p--

操作說明

  1. 操作數(shù)是指針
  2. 自增自減++--優(yōu)先級高于解引用*

計算過程

  1. 運算++/--宝当,返回的是p的值(地址),然后p自加/自減胆萧。
  2. 運算*庆揩,獲取p指向的值俐东。

等價于

*p;
p=p+1;

自增自減 相當于
*q++ *(q++)
*q-- *(q--)

*++p/*--p

操作說明

  1. 操作數(shù)是指針
  2. 前綴自增自減++--和解引用*的結合律是自右向左订晌。
  3. 前綴自增自減++虏辫、--在解引用*的右邊,優(yōu)先計算锈拨。

計算過程

  1. 運算++/--砌庄,p自加/自減,返回的是p自加/自減后的值(地址)奕枢。
  2. 運算*娄昆,獲取p指向的值。
自增自減 相當于
*++q *(++q)
*--q *(--q)

++*q/--*q

操作說明

  1. *操作數(shù)是指針缝彬,前綴自增自減++萌焰、--操作數(shù)是指針指向的值。
  2. 前綴自增自減++谷浅、--和解引用*的結合律是自右向左扒俯。
  3. 解引用*在前綴自增自減++--的右邊一疯,優(yōu)先計算撼玄。

計算過程

  1. 運算*,獲取p指向的值墩邀。
  2. 運算++/--掌猛,p指向的值自加/自減。
自增自減 相當于
++*q ++(*q)
--*q --(*q)

如果一個表達式里有多個運算符磕蒲,則先進行優(yōu)先級比較留潦,先執(zhí)行優(yōu)先級高的運算符;如果優(yōu)先級相同辣往,那就看結合性兔院,根據(jù)結合方向來做運算。

  • 問題
    指針與指針可以相加嗎站削?
    在不同數(shù)組中可以執(zhí)行上面的操作嗎坊萝?
    試一下編譯下面程序
#include <stdio.h>

int main () {

    int arr[]={100,101,102,103,104,105};
    for(i=0;i<5;++i){
        printf("%p\n",arr++);
    }
    return 0;
}

1.2 比較運算符

==!=许起、<十偶、<=>园细、>=
本質是比較內存中的地址惦积。

#include <stdio.h>
int main () {
    int arr[]={100,101,102,103,104,105};
    int* p = arr;
    for(int i=0;i<5;++i){
        printf("%p\n",p++);
    }
    return 0;
}

數(shù)組中的元素地址線性遞增。

1.3 單位長度

從上面可以看到猛频,指針的加1減1狮崩,地址并非加1減1蛛勉。

int iarr[] = {1,2,3,4,5,6};
int* p = iarr;
for(int i=0;i<5;++i){
    printf("%p\n",p++);
}

char carr[] = {1,2,3,4,5,6};
char* q=carr;
for(int i=0;i<5;++i){
    printf("%p\n",p++);
}

  • 應用范圍
    指針的算術運算表示在一片連續(xù)空間上的移動。
    指針的比較運算也是用于一片連續(xù)空間的地址比較睦柴。
    常用于數(shù)組等連續(xù)內存诽凌。

2. 指針類型

  1. 無論指向什么類型,所有指針的大小都是一樣的坦敌,都是地址的大小侣诵。
char* str;
short* ps;
int* pn;
long* pl;
long long* pll;
float* pf;
double* pd;
long double* pld;

  1. 指針類型轉換

指向不同類型的指針不能直接相互賦值(特例void*),需要強制類型轉換狱窘。

char* str = "abcd";
int* p = str;

指針類型轉換沒有改變指針內的地址杜顺,也沒有改變指針指向的值,只是改變了移動的單位長度训柴。

#include <stdio.h>
int main(){
    char* str = "abcdef";
    int* p=(int*)str;
    p++;
    char* q = (char*)p;
    printf("%c\n",*q);
}

  1. void類型的指針

void*是一種很特別的指針哑舒,表示指向未知類型的指針,并不指定它是指向哪一種類型的數(shù)據(jù)幻馁,而是根據(jù)需要轉換為所需數(shù)據(jù)類型洗鸵。

int n = 0;
int* p = &n;
void* q = p;
int* k = (int*) q;

指針作用小結

  1. 較大數(shù)據(jù)結構體傳入時做參數(shù)。
  2. 傳入數(shù)組后仗嗦,對數(shù)組做操作膘滨。
  3. 函數(shù)需要多個返回值時,作為返回值參數(shù)稀拐。
  4. 動態(tài)申請內存火邓。
  5. 避免使用未初始化指針、空指針和野指針德撬。

3. 數(shù)組指針 vs 指針數(shù)組

3.1 數(shù)組指針

指向一個數(shù)組指針稱為數(shù)組指針铲咨。

int n = 0;
int* p = &n;
int arr[] = {1,2,3,4,5,6};
int* q = arr;

3.2 指針數(shù)組

指針是一個類型,也可以組成一個數(shù)組蜓洪,這樣的數(shù)組稱為指針數(shù)組纤勒。

#include <stdio.h>

int main(){
    int a = 1;
    int b = 2;
    int c = 3;
    int* p[] = {&a,&b,&c};
    for(int i=0;i<3;++i){
        printf("%d\n",*p[i]);
    }
    for(int i=0;i<3;++i){
        printf("%d\n",**(p+i));
    }
}

[]的優(yōu)先級高于*,那么p先和[]結合隆檀,說明這是一個數(shù)組摇天。再和int*結合,說明這個數(shù)組里的每個元素都是一個指針恐仑,每個元素都能保存一個地址泉坐。


4. 常量指針 vs 指針常量

4.1 常量指針const int *p

可以寫作int const *ppint*類型裳仆,const修飾的是*p腕让,所以*p是常量,表示p指向的地址里的值不可修改歧斟,也就是說纯丸,p里的值不能再重新賦值了司训,但是可以修改p指向的地址。

int a = 10;
int b = 20;
const int *p = &a;
p = &b;      // 可以
*p = 100;    // 錯誤

4.2 指針常量int * const p

pint*類型液南,那么const修飾的是p,所以p是常量勾徽,表示p指向的地址不可修改滑凉,即p不能再指向別的地方了,但是可以修改p指向的這個地址里的值喘帚。

int a = 10;
int b = 20;
int * const p = &a;
p = &b;      // 錯誤
*p = 100;    // 允許

4.3 常量指針常量const int * const p

pint*類型畅姊,兩個const分別修飾了p*p, 所以p*p都是常量吹由,表示p指向的地址不可修改若未,同時p指向的地址里的值也不可修改。

int a = 10;
int b = 20;
const int *const p = &a;
p = &b;       // 錯誤
*p = 100;     // 錯誤

自由的代價倾鲫,是永遠的警惕粗合。-- C Primer Plus
你定義了一個指針,那就一定要知道這個指針指向的什么地方乌昔,而且你要保證這個指針是真實有效的隙疚,否則我就用程序崩潰來懲罰你。

No. 例子 名稱 指向的值 地址
1 const int *p/int const *p 常量指針 不可改變 可改變
2 int* const p 指針常量 可改變 不可改變
3 const int * const p 常量指針常量 不可改變 不可改變

*之前的const修飾指向的變量磕道,*之后的const修飾指針供屉。

問題
下面的q是什么類型指針?

const int *p,*q;
int const *p,*q;
int* const p,*q;
const int * const p,*q;


0地址

#include <stdio.h>

int main(){
    int *p = 0;
    printf("%d\n",*p);
}

0地址是內存中不能訪問的地址溺蕉。在C語言中伶丐,標準庫定義NULL表示0地址。
通常用來表示如下:

  1. 指針沒有初始化
  2. 返回指針無效
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末疯特,一起剝皮案震驚了整個濱河市哗魂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辙芍,老刑警劉巖啡彬,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異故硅,居然都是意外死亡庶灿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門吃衅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來往踢,“玉大人,你說我怎么就攤上這事徘层【唬” “怎么了利职?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瘦癌。 經(jīng)常有香客問我猪贪,道長,這世上最難降的妖魔是什么讯私? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任热押,我火速辦了婚禮,結果婚禮上斤寇,老公的妹妹穿的比我還像新娘桶癣。我一直安慰自己,他們只是感情好娘锁,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布牙寞。 她就那樣靜靜地躺著,像睡著了一般莫秆。 火紅的嫁衣襯著肌膚如雪间雀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天镊屎,我揣著相機與錄音雷蹂,去河邊找鬼。 笑死杯道,一個胖子當著我的面吹牛匪煌,可吹牛的內容都是我干的。 我是一名探鬼主播党巾,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼萎庭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了齿拂?” 一聲冷哼從身側響起驳规,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎署海,沒想到半個月后吗购,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡砸狞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年捻勉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刀森。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡踱启,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情埠偿,我是刑警寧澤透罢,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站冠蒋,受9級特大地震影響羽圃,放射性物質發(fā)生泄漏。R本人自食惡果不足惜抖剿,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一统屈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧牙躺,春花似錦、人聲如沸腕扶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽半抱。三九已至脓恕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窿侈,已是汗流浹背炼幔。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留史简,地道東北人乃秀。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像圆兵,于是被迫代替她去往敵國和親跺讯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型殉农。 運用指針編程是C語言最主要的風格之一刀脏。利用指針變量可以表示各種數(shù)據(jù)結構; ...
    朱森閱讀 3,449評論 3 44
  • C語言是面向過程的超凳,而C++是面向對象的 C和C++的區(qū)別: C是一個結構化語言愈污,它的重點在于算法和數(shù)據(jù)結構。C程...
    小辰帶你看世界閱讀 950評論 0 6
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,523評論 1 51
  • 1. 指針運算 1.1 算術運算 加減+轮傍、-指針與整數(shù)相加:表示指針指向下個變量暂雹。指針與整數(shù)相減:表示指針指向上個...
    jdzhangxin閱讀 736評論 0 0
  • 第十章 指針 1. 地址指針的基本概念: 在計算機中,所有的數(shù)據(jù)都是存放在存儲器中的创夜。一般把存儲器中的一個字節(jié)稱為...
    堅持到底v2閱讀 1,074評論 2 3