C語言中的指針——C之精髓?

大神們經(jīng)常說C語言是一種底層語言氏身,不像python啊巍棱,java啊這種高級編程語言。一直理解的不大好蛋欣,也不明白為啥C語言就底層了拉盾。只是覺得老拿C語言做單片機嵌入式的開發(fā),是不是就是底層了豁状。最近看數(shù)據(jù)結(jié)構(gòu)和算法,一會一個指針一會一個指針的總是弄混倒得,感覺對指針有一種若即若離的感覺泻红,既陌生有熟悉。決定重新回過頭來看他霞掺。

1指針

  • 地址和指針有著千絲萬縷的關(guān)系谊路,計算機內(nèi)存中的每個位置都有一個地址標識,C語言中用指針來表示地址菩彬,聲明一個指針變量并不會自動給他分配任何內(nèi)存缠劝。在對指針進行間接訪問前,指針必須初始化:要么指向現(xiàn)有內(nèi)存(賦值)骗灶,要么動態(tài)分配新的內(nèi)存(malloc)惨恭。
  • C標準定義了NULL指針,它作為一個特殊的指針常量耙旦,表示不指向任何位置脱羡,因而對一個NULL指針進行解引用操作同樣也是非法的。因而在對指針進行解引用操作的所有情形前,如常規(guī)賦值锉罐、指針作為函數(shù)的參數(shù)帆竹,首先必須檢查指針的合法性- 非NULL指針。
  • 所有的指針進行顯示的初始化是種好做法

如果知道指針被初始化為什么地址脓规,就該把它初始化為該地址栽连,否則初始化為NULL
在所有指針解引用操作前都要對其進行合法性檢查,判斷是否為NULL指針侨舆,這是一種良好安全的編程風(fēng)格

1.1指針運算

  1. 自增自減:指向下一個地址或指向上一個地址
  2. 同類型指針相減:如果兩個指針指向同一個數(shù)組秒紧,相減的結(jié)果就是兩個指針之間的元素數(shù)目。注意:指針相加沒有意義态罪;不同類型的指針相減也沒有意義
  3. 指針加上或減去一個整型值:如一個float類型的指針加3表示指針的值增加3個float類型的大小噩茄。
  • 如果對一個指針進行減法運算,產(chǎn)生的指針指向了數(shù)組中第1個元素前面的內(nèi)存位置复颈,那么它是非法的绩聘。
  • 加法運算稍微不同,如果產(chǎn)生的指針指向了數(shù)組中最后一個元素后面的那個內(nèi)存地址耗啦,它是合法的,但不能對該指針執(zhí)行解引用操作凿菩,不過之后就不合法了(這和STL中迭代器尾部元素可指向尾部元素的下一個位置是一樣的道理)

插播:typedef 和#define有什么區(qū)別呢?

#define 是預(yù)處理指令帜讲,在編譯預(yù)處理時進行簡單地替換 衅谷,不做正確性檢查。

#define A 3+4
在程序中遇到3*A則會將A進行簡單的替換->3*3+4=13
再例如:
#define int_ptr int* int_ptr a,b; //a是int*類型的似将,而b是int型的
typedef int* int_ptr int_ptr a,b; //a和b都是int*類型的

typedef是在編譯時處理的获黔,他是在自己的作用域里給一個已經(jīng)存在的類型一個別名。

typedef char ElemType 把一個char型起一個別名叫ElemType在验,這樣的好處是玷氏,當你想將程序中的數(shù)據(jù)類型換成int型的時候,不用一個一個修改腋舌,只需修改typedef char ElemType為typedef int ElemType即可盏触。

1.2void *指針

C中提供一個特殊的指針類型: void *,它可以保存任何類型對象的地址。
void *表明該指針與一地址值相關(guān)块饺,但不清楚存儲在此地址上的對象的類型拄查。void *指針只支持以下幾種操作:

  • 與另一個指針比較
  • 給另外一個void *指針賦值
  • void *指針當函數(shù)參數(shù)或返回值
    不允許使用void *指針操作它指向的對象拴袭,值得注意的是函數(shù)返回void *類型時返回一個特殊的指針類型麻献,而不是向返回void 類型那樣無返回值赌渣。

1.3函數(shù)指針和指針函數(shù)

  • 函數(shù)指針 int* f(int a, int b):本質(zhì)是個指針,它指向的是函數(shù)淮腾,指向函數(shù)的指針包含了函數(shù)的地址召庞,可以通過它來調(diào)用函數(shù)岛心。
  • 指針函數(shù) int (*f)(int a, int b):本質(zhì)是個函數(shù),它的返回值是某個類型的指針

2 數(shù)組和指針

知乎上有個大神說:在軟開行業(yè)里有一句話叫沒有什么是不能通過增加一個抽象層解決的篮灼。比如說忘古,數(shù)組就是對“一系列連續(xù)內(nèi)存單元”的抽象,它的外觀表現(xiàn)為“一個固定大小的容器”知乎連接诅诱。從這個角度上來理解髓堪,似乎數(shù)組比指針更“高級”一些,指針相對更底層娘荡。

指針和數(shù)組的愛恨情仇

2.1數(shù)組名

  1. 聲明時:數(shù)組的屬性和指針的屬性不同干旁,在聲明數(shù)組時,同時分配了用于容納數(shù)組元素的空間炮沐;而聲明一個指針時争群,只分配了用于容納指針本身的空間。
  2. 表達式中:需要注意大年,數(shù)組名是指向數(shù)組第一個元素的首地址换薄,其本質(zhì)是一個常量指針(常指針),指針自身的值不能被改變翔试,如聲明一個數(shù)組:int arr[3]={1,2,3}轻要,則不能出現(xiàn)arr++,或arr+=3這類語句。但是可以有int num=*(arr+2)指向第三個元素
  3. 通過數(shù)組名引用數(shù)組元素時:改變第二個元素的值為100垦缅,arr[1]=100;當使用[]的方式引用數(shù)組元素時冲泥,在編譯器中都會轉(zhuǎn)換成指針的形式操作,arr+1和&arr[1]是一樣的壁涎,都表示第二個元素的首地址凡恍。
  4. 作為函數(shù)參數(shù):不管以指針的形式還是數(shù)組名的形式作為函數(shù)的參數(shù)時都會被轉(zhuǎn)換成指針。
    void array_to_pointer(int *ia){……}  //無需轉(zhuǎn)換
    void array_to_pointer(int ia[ ]){……}  //被轉(zhuǎn)換成*ia
    void array_to_pointer(int ia[100 ]){……}  //被轉(zhuǎn)換成*ia
void array_test(int ia[100])//ia被轉(zhuǎn)換成了指針不再是常指針了U颉=涝汀!
{
  double da[10];
  printf("%d", sizeof( ia ));
  ia++;      //沒錯誤庞溜,按指針進行處理而非數(shù)組名
  //da++;   //編譯錯誤,數(shù)組名是常指針
}

2.2指向數(shù)組的指針

指向數(shù)組的指針主要是用來對二維數(shù)組進行操作的碑定。
理解一下 int (*p)[100]:由于括號的優(yōu)先級是最高的流码,所以首先執(zhí)行解引用,表明了p是一個指針延刘,接下來是數(shù)組下標的引用漫试,說明p指向的是某種類型的數(shù)組,前面的int表明p指向的這個數(shù)組的每個元素都是整數(shù)碘赖。
當對一個一位數(shù)組的數(shù)組名取&操作時驾荣,返回的是一個指向數(shù)組的指針外构。
例如:
int arr[100]={0};//聲明一個數(shù)組
int *p=&arr;//一個指向數(shù)組的指針
int *q=arr; //arr是數(shù)組的首地址,q指向了數(shù)組的第一個元素

2.3指針數(shù)組

在聲明一個指向數(shù)組的指針時千萬不要丟到那個括號播掷,如:int (*p) [100]; 如果丟掉了括號那就完全改變了意圖审编,從而意外地聲明了一個指針數(shù)組。
指針數(shù)組就是一個數(shù)組他的所有元素都是指針歧匈。

int (\*p)[100];//指向數(shù)組的指針
int* p[100];//指針數(shù)組垒酬,以p為數(shù)組名的數(shù)組中存放的都是指針元素

插播:指針常量和常量的指針...

常量指針: const char* ptr ="hello"; char const* ptr="hello";內(nèi)容不能改,指針可改
指針常量: char* const ptr="hello"; 指針不能改件炉,內(nèi)容可改
指向常量的常指針:const int* const p;指針和內(nèi)容都不能改

帶兩個const 的好區(qū)分勘究,就是都不能改。怎么區(qū)分指針常量和常量指針呢斟冕?
1. 看const 和*的排列順序

int const* p;   const * 即常量指針
const int* p;   //const * 即常量指針
int* const p;   //* const 即指針常量

2. 看const離誰近口糕,即從右向左看

int const* p;   //const修飾的是*p,即*p的內(nèi)容不可通過p改變磕蛇,但p不是const景描,p可以修改,*p不可修改孤里;
const int* p;   //同上
int* const p;   //const修飾的是p伏伯,p是指針,p指向的地址不能修改捌袜,p不能修改说搅,但*p可以修改;

以上只是關(guān)于C語言指針的一些皮毛虏等,剩下的東西后續(xù)再補充弄唧。通過今天的學(xué)習(xí),對C語言底層的地位有了新的認識霍衫,大概是他因為跟硬件層息息相關(guān)候引。指針的存在讓程序員可以自由地對內(nèi)存進行操作,C語言賦予了程序員極大地自由的同時也帶來了極大的隱患敦跌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末澄干,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子柠傍,更是在濱河造成了極大的恐慌麸俘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惧笛,死亡現(xiàn)場離奇詭異从媚,居然都是意外死亡,警方通過查閱死者的電腦和手機患整,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門拜效,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喷众,“玉大人,你說我怎么就攤上這事紧憾〉角В” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵稻励,是天一觀的道長父阻。 經(jīng)常有香客問我,道長望抽,這世上最難降的妖魔是什么加矛? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮煤篙,結(jié)果婚禮上斟览,老公的妹妹穿的比我還像新娘。我一直安慰自己辑奈,他們只是感情好苛茂,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鸠窗,像睡著了一般妓羊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稍计,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天躁绸,我揣著相機與錄音,去河邊找鬼臣嚣。 笑死净刮,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的硅则。 我是一名探鬼主播淹父,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怎虫!你這毒婦竟也來了暑认?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤大审,失蹤者是張志新(化名)和其女友劉穎蘸际,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饥努,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡捡鱼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年八回,在試婚紗的時候發(fā)現(xiàn)自己被綠了酷愧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驾诈。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖溶浴,靈堂內(nèi)的尸體忽然破棺而出乍迄,到底是詐尸還是另有隱情,我是刑警寧澤士败,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布闯两,位于F島的核電站,受9級特大地震影響谅将,放射性物質(zhì)發(fā)生泄漏漾狼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一饥臂、第九天 我趴在偏房一處隱蔽的房頂上張望逊躁。 院中可真熱鬧,春花似錦隅熙、人聲如沸稽煤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酵熙。三九已至,卻和暖如春驰坊,著一層夾襖步出監(jiān)牢的瞬間匾二,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工庐橙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留假勿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓态鳖,卻偏偏與公主長得像转培,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子浆竭,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型浸须。 運用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu)邦泄; ...
    朱森閱讀 3,446評論 3 44
  • void* 類型指針:通用變體類型指針;可以不經(jīng)轉(zhuǎn)換站宗,賦給其他指針闸准,函數(shù)指針除外;malloc返回的就是void*...
    冰吉凌閱讀 3,329評論 0 18
  • 轉(zhuǎn)自CSDN博客 原文鏈接:http://blog.csdn.net/xinyuwuxian/article/de...
    傻彬兒閱讀 739評論 0 0
  • 姓名:周立 zhou li 公司:寧波大發(fā)化纖有限公司 【日精進打卡第104天】 【知~學(xué)習(xí)】 (六項精進)大綱...
    周立zhouli閱讀 103評論 0 0
  • 清早梢灭,隨著擁擠的人群踏上地鐵一號線的列車夷家。刺骨的冷氣在進入車廂的瞬間,就覆蓋了整個身體敏释。所有的汗毛都隨寒意樹立起...
    無邊的藍海閱讀 470評論 0 1