各位老鐵們,大家好,今天由我來為大家分享c語言指針用法簡單舉例,以及c語言指針編程例題的相關問題知識,希望對大家有所幫助。如果可以幫助到大家,還望關注收藏下本站,您的支持是我們最大的動力,謝謝大家了哈,下面我們開始吧!
C語言指針的用法
C語言指針的一些用法
在C語言中,任何類型的指針的大小是4個字節(jié),因為存放的都是地址。
int*p;//定義了一個整型指針,可以存放整型數(shù)據(jù)的地址。
p=&a;(p就了存放a的地址,也就是說p指向了a,*p就等于3)
char*p="abcdef";//字符指針,p存放的是第一個字符(a)的地址,*p==a;
inta1[10];//整型數(shù)組,a1是一個數(shù)組,存放整型(int)數(shù)據(jù)。
都說C語言的指針很難,用不好很容易出錯,那為何還要用指針呢你能舉例說說嗎
1.分析問題
整個問題,從提問者的角度,等價于兩個子問題:
子問題1:為什么C語言要引入指針?
子問題2:指針怎么才能用好?
2.子問題1的分析現(xiàn)在來分析子問題1。要回到這個問題,要回顧計算機程序的執(zhí)行原理:
現(xiàn)代通用計算機基本上都遵循馮·諾依曼結(jié)構(gòu)。
馮·諾依曼結(jié)構(gòu)的精髓在于:將計算機指令與數(shù)據(jù)一視同仁,都放入內(nèi)存中處理。所以計算機程序執(zhí)行的過程,實際上就是不斷從內(nèi)存中取出指令,再從內(nèi)存中取出數(shù)據(jù),指令作用于數(shù)據(jù)得到結(jié)果,結(jié)果再放回內(nèi)存的過程。
從這個過程可以看出,程序的整個運行都是圍繞內(nèi)存進行的。既然指令和數(shù)據(jù)都放在內(nèi)存中,那么執(zhí)行哪條指令、取哪個數(shù)據(jù)、結(jié)果放到哪里,都需要精確定位內(nèi)存的具體位置。
C語言作為開發(fā)Unix操作系統(tǒng)而創(chuàng)造出來的編程語言,天然需要具備操作系統(tǒng)底層的能力;而從上述程序運行的視角來看,所謂的系統(tǒng)底層能力,核心在于對內(nèi)存位置的定位能力。C語言用于對內(nèi)存進行定位的“武器”就是指針。
一言以蔽之:C語言之所以引入指針,是由C語言誕生的歷史背景和所要承載的歷史使命決定的——開發(fā)操作系統(tǒng),要用強大的操控系統(tǒng)底層的能力,系統(tǒng)底層的核心是對內(nèi)存的定位操作。
3.子問題2的分析很多同學被指針搞懵的原因在于:大陸的C語言入門的教材基本上都是譚浩強的《C語言程序設計》,這本教材講述指針過于繁瑣,沒有抓住指針的本質(zhì)。
指針的本質(zhì)就是內(nèi)存地址。
記住這一點之后,你就可以游刃有余了。以下筆者對初學者最容易暈菜的幾個概念進行最凝練的解釋。
3.1多級指針一級指針就是一次性指向目標內(nèi)存地址、二級指針就是分兩段指向最終目標地址(第一級相當于先指向一個“中間驛站”,第二級再從“中間驛站”指向最終目標地址)……依次類推,這樣哪怕給你一個N級指針,你也不會懵逼。
3.2指針數(shù)組與數(shù)組指針說白了,考的并不是計算機知識,考的是語文知識:)
兩個術語都是偏正短語:前者的被修飾詞(中心詞)是數(shù)組,后者的被修飾詞(中心詞)是指針;前者這個數(shù)組里的每個元素都是指針,后者這個指針指向的是一個數(shù)組(一片連續(xù)的內(nèi)存區(qū))。
c語言指針怎么用
1.指針的使用使得不同區(qū)域的代碼可以輕易的共享內(nèi)存數(shù)據(jù),這樣可以使程序更為快速高效;
2.C語言中一些復雜的數(shù)據(jù)結(jié)構(gòu)往往需要使用指針來構(gòu)建,如鏈表、二叉樹等;
3.C語言是傳值調(diào)用,而有些操作傳值調(diào)用是無法完成的,如通過被調(diào)函數(shù)修改調(diào)用函數(shù)的對象,但是這種操作可以由指針來完成,而且并不違背傳值調(diào)用。
C語言指針怎樣快速掌握指針用處大嗎
C語言指針就是這門語言的靈魂,說難學,那肯定是有難度的,畢竟這是業(yè)界公認的。但是如果你熟練掌握了指針的話,它又將會成為你手中的一柄利器。下面就詳細的分享一下指針該如何深入的去理解它以及如何熟練的應用它
理解指針首先,你需要掌握兩個運算符“*”和“&”;
“&”運算符:取對象在內(nèi)存中的地址
“*”運算符:取內(nèi)存中地址上的對象(值);
大家一定要深刻的理解上面兩個運算符,然后才能去進一步理解指針;
inta=100;這一行代碼我想大家都沒問題。那么“&a”返回的就是對象(變量)a在內(nèi)存中的地址,它是一個16進制數(shù)。
然后用“*”號去a的地址去取對象:“*(&a)”,,就能取到對象a,也就就是100;
接下來進入重點了,指針,本身也是一個變量(對象),它本身占用內(nèi)存,但是它只存地址(別人的地址),它存的誰的地址我們就稱它為指向誰的指針;
int*p=&a;int*p_2=newint(200);先不管他的類型申明,只看變量本身p和p_2。前面講到指針存放的是對象的地址,那么可以理解為指針是一個地址變量,那么賦值的話就需要也賦一個地址給它一個地址。int*和char*都可以表示地址類型,它們的區(qū)別就是地址所存的值得類型不同,一個是存整型,一個是存字符型;
對指針取值的話,就是用“*”號,后面接對象地址,也就是指針變量,所以*p和*p_2就分別是a和200;
指針的運用指針并不是C/C++獨有的,像C#和java等其實也是有指針的,只不過都被語言本身用其他的方式替代和封裝了一般程序員接觸不到,C/C++就不一樣,它是直接將指針暴露給開發(fā)者,因為大部分牽涉到指針的都與內(nèi)存有關,而計算機內(nèi)存很重要,萬一出什么問題可能系統(tǒng)都會崩潰,下面就簡單來看一下程序在運行時指針與內(nèi)存之間到底是個什么樣的關系:
先看一段代碼:
#include<stdio.h>
#include<string>
#include<iostream>
#include<time.h>
usingnamespacestd;
classpeople
{
public:
people();
~people();
stringName;
intage;
boolsex;
charinfo[1024];
voidrun(){}
voideat(){}
private:
};
people::people()
{
}
people::~people()
{
}
intmain()
{
people*p1=newpeople();
cout<<p1<<endl;
cout<<&p1<<endl;
cout<<sizeof(p1)<<endl;
cout<<sizeof(*p1)<<endl;
system("pause");
return0;
}
直接運行看結(jié)果:
分析接下來來一一進行分析:
首先people*p1=newpeople();這一句是類的一個實例化,系統(tǒng)會給people實例化一個對象*p并且給它在堆上開辟空間,注意是在堆上,開辟的空間用來存儲對象的數(shù)據(jù)。數(shù)據(jù)包括哪些?就是對象的屬性和虛函數(shù)指針,但是函數(shù)并不存儲在各對象中。因此run()和eat()方法是不存在對象*p指向的內(nèi)存處的。
cout<<p1<<endl;輸出的是00279360,這是一個地址,是系統(tǒng)給newpeople()對象分配的地址。
cout<<&p1<<endl;輸出的是0012FD90,這也是地址,但這是指針變量p本身的地址。
cout<<sizeof(p1)<<endl;
cout<<sizeof(*p1)<<endl;
通過這兩個輸出就能有更清晰的認識了,p1本身只占用4個字節(jié)的空間,而它所指向的對象的地址所占的空間就很大,等于類中所有數(shù)據(jù)類型所占空間之和。
接下來在main函數(shù)里寫一點邏輯:
圖解我們來看一下程序運行時間,指針和內(nèi)存是怎么工作的。這里畫一個圖給大家:
程序在運行時,數(shù)據(jù)主要是存儲在棧、堆、代碼區(qū)、全局區(qū)。代碼區(qū)主要就是存代碼中出現(xiàn)的一些字符常量、方法等,比如這里代碼中給對象的Name屬性賦的值“xiaoli”之類的都是存在此處,然后我們通過new出來的對象,都是由堆通過計算好類中各屬性所需空間然后開辟出來的。這里p3不是通過new開辟出來的,所以他是存在棧上的并且地址是固定的,是不能更改的,而p1和p2是能更改的。
改變地址如此,我們?nèi)齻€對象互相賦值后會發(fā)生什么呢?
對比代碼和輸出結(jié)果我們發(fā)現(xiàn)了什么?賦值后p1和p2本身的地址并無改變,但是他所指向的內(nèi)存都編程p3所在的內(nèi)存了。下面用圖解給大家看一下:
注意,此處原來的p1和p2指向的內(nèi)存由于是new出來的我們需要手動釋放它。所以我們在重新賦值之前要將這兩塊內(nèi)存刪除掉deletep2;deletep1;
改變地址的值如果我將代碼中的p2=&p3;換成*p2=p3呢?我們看下輸出結(jié)果:
造成這種情況的原因,其實這就牽涉到指針的兩種賦值問題:一種是改變指向的地址,一種是改變本身指向地址的值p2=&p3是改變指向地址,*p2=p3是改變指向地址的值。
C語言指針到底有什么用
所有變量值保存在內(nèi)存中,而每個內(nèi)存都有一個地址,所謂地址就是一個整數(shù)編號,如同門牌號碼用于定位(專業(yè)術語叫尋址),一個地址對應一個字節(jié)(8bit)的內(nèi)存單元。
如今的編譯器,一個整數(shù)int類型的值占用32位bit,也就是4字節(jié),編譯器將第一個字節(jié)的編號定義為該整數(shù)的地址,由于保存地址的變量就像一個箭頭指向某地址,而稱為指針變量。
inta=10;//定義一個整數(shù)變量a,對其賦值10
int*p=&a;//定義一個指針變量p,對其賦值a的內(nèi)存地址,&符號意思為引用跟隨其后的變量地址。
cont<<a<<end;//輸出a的值:10
cont<<p<<end;//輸出p的值:XXXXX其實為a的地址,該地址由編譯器和運行時確定。
cont<<*p<<end;//輸出p指向的地址中的值:10,也就是a的值,*星號放在變量前面意思就是取該變量中的地址所指內(nèi)存中的值。
讀取過程為:p的值(a的地址)->尋址->取值
由于指針是一個變量的首個字節(jié)的地址,所以要告訴編譯器被指地址包含連續(xù)多少個字節(jié),因此指針也有類型。比如上面例子中聲明了p指針是個整數(shù)指針,這樣編譯器知道p指向一個4字節(jié)的內(nèi)存塊。
你可以將指針變量看做一般的整數(shù)變量來理解,用來保存一個整數(shù)(地址是個整數(shù)),只是,該整數(shù)代表著某地址,在這里是a的地址。
在C/C++中很靈活,但是也很危險,也很難學,如果指針指向錯誤的地址會引起程序崩潰,因此在C#中已經(jīng)被微軟封裝了,但內(nèi)部還是有指針的。
如果有必要,C#中也可以使用指針,使用非安全代碼,在項目生成選項卡中勾選“允許非安全代碼”,然后就可以使用指針了,不過不建議這么做。
unsafe
{
inta=10;
int*p=&a;
}
OK,本文到此結(jié)束,希望對大家有所幫助。