A. 單片機中程序指針、數據指針、堆棧指針區別是什麼
首先,你要明白一個概念,指針,是做什麼的?答案是,指針,是指向地址的。
程序指針,指向的空間,在物理上是Flash,在邏輯上,就是代碼空間。比如說51單片機的PC指針,指向的就是Flash,即程序下一步要執行的指令的地址。
數據指針,指向的空間,在物理上有Flash和RAM,在邏輯上是Flash里的常數空間和數據空間,注意,是對於單片機來說,對於我們的電腦,常數空間不是在Flash上。
比如說51單片機的DPTR,如果用MOVC
A,@A+DPTR,此時,就是指向常數空間,如果用
MOVX
A,@A+DPTR就是指向的數據空間。
堆棧指針,指向的空間,在物理上是RAM,在邏輯上,就是數據空間,是特定的數據空間,堆棧是數據空間中單獨劃分出來,專門用於寄存中間結果的內存空間。
數據指針和堆棧指針主要有兩個區別:
一是數據指針可以指向Flash,即可以指向常數,比如說我們定義一個數組
unsigned
char
code
Table[99],此時,就是DPTR可以指向常數空間。堆棧指針是不可以的,只能是指向RAM。
第二個區別,堆棧指針指向的是特定的數據空間,這個特定的數據空間,是從整個數據空間里劃分出來,專門用於作堆棧用的,堆棧區間一旦劃分出來,堆棧指針在規則上,就只能在這個范圍內活動,如果出了這個范圍,可能導致整個程序的崩潰。而數據指針在規則上,可以指向整個數據空間,但是,可以讀堆棧空間,不應該去修改,否則也可能導致程序的崩潰。
B. 單片機里的 DPTR 和 PC 分別代表什麼
DPTR數據指針
數據指針(DPTR)是某些單片機中一個功能比較特殊的寄存器,是一個16位的特殊功能寄存器, 其高位位元組寄存器用DPH表示,低位位元組寄存器用DPL表示,DPTR既可以作為一個16位的寄存器來處理,也可以作為兩個獨立的8位寄存器來使用。主要功能是存放16位地址,作為片外RAM定址用的地址寄存器(間接定址),故稱數據指針,也可以將外部RAM中地址的內容傳送到內部RAM的地址所指向的內容中。
2. PC程序指針:
PC——程序計數器,功能:用來指示下一條指令的地址(邏輯地址即偏移量),一般情況下,系統指示對其進行加1操作,擔當遇到轉移指令,如JMP,CALL,LOOP等時系統就會將跳轉到的指令地址保存在PC中
C. 什麼是指針
指針其實就是變數,只不過指針變數指向的不是某個具體的值,而是指向這個值所在的內存的地址.指針和其它變數一樣,指針是基本的變數,所不同的是指針包含一個實際的數據,該數據代表一個可以找到實際信息的內存地址。這是一個非常重要的概念。許多程序和思想依靠指針作為他們設計的基礎。
開始
怎樣定義一個指針呢?除了你需要在變數的名稱前面加一個星號外,其它的和別的變數定義一樣。舉個例子,以下代碼定義了兩個指針變數,它們都指向一個整數。
int* pNumberOne;
int* pNumberTwo;
注意到兩個變數名稱前的前綴』p』了么?這是一個慣例,用來表示這個變數是個指針。
現在,讓我們將這些指針實際的指向某些東西:
pNumberOne = &some_number;
pNumberTwo = &some_other_number;
『&』符號應該讀作」什麼什麼的地址」,它返回一個變數在內存中的地址,設置到左側的變數中。因此,在這個例子中,pNumberOne設置和some_number的地址相同,因此pNumberOne現在指向some_number。
現在,如果我們想訪問some_number的地址,可以使用pNumberOne。如果我們想通過pNumberOne訪問some_number的值,那麼應該用*pNumberOne。這個星號表示解除指針的參照,應該讀作「什麼什麼指向的內存區域」。
到現在我們學到了什麼?舉個例子
喲,有許多東西需要理解。我的建議是,如果你有哪個概念沒有弄清楚的話,那麼,不妨再看一遍。指針是個復雜的對象,可能需要花費一段時間來掌握它。
這兒有一個例子示範上面所將的概念。這是用C寫的,沒有C++擴展。
#include <stdio.h>
void main()
{
// 申明變數
int nNumber;
int *pPointer;
//賦值
nNumber = 15;
pPointer = &nNumber;
// 輸出nNumber的值
printf("nNumber is equal to : %d\n", nNumber);
// 通過pPointer修改nNumber的值
*pPointer = 25;
// 證明nNumber已經被改變了
// 再次列印nNumber的值
printf("nNumber is equal to : %d\n", nNumber);
}
通讀一遍,並且編譯樣例代碼,確信你理解了它為什麼這樣工作。如果你准備好了,那麼繼續。
一個陷阱!
看看你能否發現下面這段程序的毛病:
#include <stdio.h>
int *pPointer;
void SomeFunction();
{
int nNumber;
nNumber = 25;
//將pPointer指向nNumber
pPointer = &nNumber;
}
void main()
{
SomeFunction(); //用pPointer做些事情
// 為什麼會失敗?
printf("Value of *pPointer: %d\n", *pPointer);
}
這段程序先調用SomeFunction函數,該函數創建一個叫做nNumber的變數,並將pPointer指向它。那麼,問題是,當函數退出時,nNumber被刪除了,因為它是一個局部變數。當程序執行到局部變數定義的程序塊以外時,局部變數總是被刪除了。這就意味著,當SomeFunction函數返回到main函數時,局部變數將被刪除,因此pPointer將指向原先nNumber的地址,但這個地址已經不再屬於這段程序了。如果你不理解這些,那麼重新閱讀一遍關於局部變數和全局變數的作用范圍是明智的選擇。這個概念也是非常重要的。
那麼,我們如何解決這個問題呢?答案是使用大家都知道的一個方法:動態分配。請明白C和C++的動態分配是不同的。既然現在大多數程序員都使用C++,那麼下面這段代碼就是常用的了。
動態分配
動態分配可以說是指針的關鍵所在。不需要通過定義變數,就可以將指針指向分配的內存。也許這個概念看起來比較模糊,但是確實比較簡單。下面的代碼示範如何為一個整數分配內存:
int *pNumber;
pNumber = new int;
第一行申明了一個指針pNumber,第二行分配一個整數內存,並且將pNumber指向這個新內存。下面是另一個例子,這次用一個浮點數:
double *pDouble;
pDouble = new double;
動態分配有什麼不同的呢?當函數返回或者程序運行到當前塊以外時,你動態分配的內存將不會被刪除。因此,如果我們用動態分配重寫上面的例子,可以看到現在能夠正常工作了。
#include <stdio.h>
int *pPointer;
void SomeFunction()
{
// make pPointer point to a new integer
pPointer = new int;
*pPointer = 25;
}
void main()
{
SomeFunction(); // make pPointer point to something
printf("Value of *pPointer: %d\n", *pPointer);
}
通讀一遍,編譯上面的代碼,確信你已經理解它是如何工作的。當調用SomeFunction時,分配了一些內存,並且用pPointer指向它。這次,當函數返回時,新內存就完整無缺了。因此pPointer仍舊指向有用的東西。這是因為使用了動態分配。確信你已經理解它了。那麼繼續向下看,了解為什麼上面的程序還會有一系列的錯誤。
內存分配和內存釋放
這里有一個問題,可能會變得十分嚴重,雖然它很容易補救。這個問題就是,雖然你用動態分配可以方便的讓內存完整無缺,確實不會自動刪除,除非你告訴計算機,你不再需要這塊內存了,否則內存將一直被分配著。因此結果就是,如果你不告訴計算機你已經使用完這塊內存,那麼它將成為被浪費的空間,因為其它程序或者你的應用程序的其它部分不能使用這塊內存。最終將導致系統因為內存耗盡而崩潰。因此這個問題相當重要。內存使用完後釋放非常容易:
delete pPointer;
需要做的就是這些。但是你必須確定,你刪除的是一個指向你實際分配的內存的指針,而不是其它任何垃圾。嘗試用delete已經釋放的內存是危險的,並且可能導致程序崩潰。
這里再次舉個例子,這次修改以後就不會有內存浪費了。
#include <stdio.h>
int *pPointer;
void SomeFunction()
{
// make pPointer point to a new integer
pPointer = new int;
*pPointer = 25;
}
void main()
{
SomeFunction(); // make pPointer point to something
printf("Value of *pPointer: %d\n", *pPointer);
delete pPointer;
}
只有一行不同,但這行是要點。如果你不刪除內存,就會導致「內存泄漏」,內存將逐漸減少,除非應用程序重新啟動,否則將不能再生。
向函數傳遞指針
傳遞指針給函數非常有用,但不容易掌握。如果我們寫一個程序,傳遞一個數值並且給它加上5,我們也許會寫出如下的程序:
#include <stdio.h>
void AddFive(int Number)
{
Number = Number + 5;
}
void main()
{
int nMyNumber = 18;
printf("My original number is %d\n", nMyNumber);
AddFive(nMyNumber);
printf("My new number is %d\n", nMyNumber);
}
但是,程序中函數AddFive的參數Number只是變數nMyNumber的一個拷貝,而不是變數本身,因此,Number = Number + 5隻是為變數的拷貝增加了5,而不是最初的在main()函數中的變數。當然,你可以運行程序,以證明這一點。
為了將值傳遞出去,我們可以傳遞這個變數的指針到函數中,但我們需要修改一下函數,以便傳遞數值的指針而不是數值。因此將void AddFive(int Number)修改為void AddFive(int *Number),增加了一個星號。下面是修改了的函數,注意,我們必須確認傳遞了nMyNumber的地址,而不是它本身。這通過增加&符號來完成,通常讀作「什麼什麼的地址」。
#include <stdio.h>
void AddFive(int* Number)
{
*Number = *Number + 5;
}
void main()
{
int nMyNumber = 18;
printf("My original number is %d\n", nMyNumber);
AddFive(&nMyNumber);
printf("My new number is %d\n", nMyNumber);
}
大家可以試著自己做個例子來實驗一下。注意在AddFive函數中Number變數前那個重要的星號。只是必須的,用來告訴編譯器我們想將5加到變數Number指向的數值,而不是將5加到指針本身。
關於函數最後需要注意的是你也可以返回一個指針。比如:
int * MyFunction();
在這個例子中,MyFunction函數返回一個指向整數的指針。
類的指針
關於指針還有兩個需要注意的問題。其中一個是結構或者類。你可以如下定義一個類:
class MyClass
{
public:
int m_Number;
char m_Character;
};
然後,你可以如下方式定義一個類變數:
MyClass thing;
你應該已經知道這些了,如果還不知道的話,那麼再將上面的內容讀一遍。定義MyClass的指針應該這么寫:
MyClass *thing;
然後你需要分配內存,並將指針指向這個內存
thing = new MyClass;
問題來了,你如何使用這個指針呢?一般的,我們寫thing.m_Number,但你不能對指針用』.』操作,因為thing不是一個MyClass對象。只是指向一個MyClass對象的指針。因此,指針thing不包含m_Number這個變數。只是它指向的結構中包含這個變數。因此,我們必須使用一個不同的協定,用->取代』.』。以下是一個例子:
class MyClass
{
public:
int m_Number;
char m_Character;
};
void main()
{
MyClass *pPointer;
pPointer = new MyClass;
pPointer->m_Number = 10;
pPointer->m_Character = 's';
delete pPointer;
}
數組的指針
你也可以構造一個指向數組的指針,如下:
int *pArray;
pArray = new int[6];
將創建一個叫做pArray的指針,指向一個包含6個元素的數組。另一種構造的方法是使用動態分配,如下:
int *pArray;
int MyArray[6];
pArray = &MyArray[0];
注意,你這里也可以不用&MyArray[0],而直接使用&MyArray取代。當然,這僅僅適用於數組。
使用指向數組的指針
一旦你有了指向數組的指針,那麼如何使用它呢?現在假設你有一個指向整數數組的指針,那麼指針開始時將指向第一個整數。舉例如下:
#include <stdio.h>
void main()
{
int Array[3];
Array[0] = 10;
Array[1] = 20;
Array[2] = 30;
int *pArray;
pArray = &Array[0];
printf("pArray points to the value %d\n", *pArray);
}
將指針移到指向數組的下一個值,可以用pArray++。也許你也可以猜出來了,我們可以用pArray+2的方式將指針向後移動兩個位置。要注意的問題是,你自己必須知道數組的上限是多少(例子中是3),因為編譯器不能檢查你是否將指針移到了數組以外,因此你可以很容易的將系統搞崩潰了。以下是個例子,顯示我們設置的三個值:
#include <stdio.h>
void main()
{
int Array[3];
Array[0] = 10;
Array[1] = 20;
Array[2] = 30;
int *pArray;
pArray = &Array[0];
printf("pArray points to the value %d\n", *pArray);
pArray++;
printf("pArray points to the value %d\n", *pArray);
pArray++;
printf("pArray points to the value %d\n", *pArray);
}
你也可以使用pArray-2這樣的方式來向前移動2個位置。不管是加或者減,你必須保證不是對指針所指向的數據的操作。這種操作指針和數組的方式在循環中是最常用的。例如for和while循環。
另外要提的是,如果你有一個指針比如int pNumberSet,你也可以把它當成數組。例如pNumberSet[0]等於*pNumberSet,並且pNumberSet[1]等於*(pNumberSet+1)。
對於數組,還有一點要注意的,如果你用new為數組分配內存,比如:
int *pArray;
pArray = new int[6];
你必須用以下方式進行刪除:
delete[] pArray;
注意delete後的[],它告訴編譯器,這是刪除整個數組,而不僅僅是第一個元素。對於數組你必須使用這種方法,否則就會有內存泄漏。
總結
一條要注意的:你不能刪除不是用new分配的內存。比如以下例子:
void main()
{
int number;
int *pNumber = number;
delete pNumber; // wrong - *pNumber wasn't allocated using new.
}
D. C語言指針基本概念及其指針變數的定義是什麼
指針是常見間接訪問方式.指針就像一個快捷方式,它指向內存的一個地址,可以通過指針就可以間接的訪問到數據。對於計算機,訪問內存的方式有兩種,直接訪問和間接訪問。直接訪問通過就是通過變數名稱去訪問。指針概念是構成C/C++的重要元素之一,是變數的一種類型,存放的是指定類型數據的地址,而同類型變數存放的是數據。
指針變數:就是一個變數,其值是可變的,與整形變數、浮點變數等等的命名規則完全相同。 「指針」是概念,「指針變數」是具體實現。指針類型說明,即定義變數為一個指針變數; 指針變數名; 變數值(指針)所指向的變數的數據類型。
(4)什麼是數據指針擴展閱讀:
與其他高級編程語言相比,C 語言可以更高效地對計算機硬體進行操作,而計算機硬體的操作指令,在很大程度上依賴於地址。指針提供了對地址操作的一種方法,因此,使用指針可使得 C 語言能夠更高效地實現對計算機底層硬體的操作。另外,通過指針可以更便捷地操作數組。在一定意義上可以說,指針是 C 語言的精髓。
E. 什麼是指針數據類型
指針是一種變數,和整型呀浮點型一樣
不同的是,指針變數裡面存儲的是一個變數的地址
比如整型指針存儲的是一個整型變數的存儲地址
最終要說的是,指針數據類型就是一種數據類型,沒什麼特殊的
只不過整型變數存儲的是整數
指針變數存儲的是地址
F. 指針與指針變數的概念是什麼
1、指針,是C語言中的一個重要概念及其特點,也是掌握C語言比較困難的部分。指針也就是內存地址,指針變數是用來存放內存地址的變數,不同類型的指針變數所佔用的存儲單元長度是相同的,而存放數據的變數因數據的類型不同,所佔用的存儲空間長度也不同。
有了指針以後,不僅可以對數據本身,也可以對存儲數據的變數地址進行操作。
2、指針變數是指存放地址的變數。因地址的改變而做出指定性質的衡量變法。
(6)什麼是數據指針擴展閱讀:
指針變數定義:
1、定義指針變數的一般形式如下:
類型名*指針變數名1,*指針變數名2,... *指針變數名n ;
2、空指針
空指針是一個特殊的指針,它的值是0,C語言中用符號常量NULL(在stdio.h中定義)表示這個空值,並保證這個值不會是任何變數的地址。空指針對任何指針類型賦值都是合法的。一個指針變數具有空指針值表示當前它沒有指向任何有意義的東西。
3、void指針
(void *)類型的指針叫通用指針,可以指向任何的變數,C語言允許直接把任何變數的地址作為指針賦給通用指針。
但是需要注意void*不能指向由const修飾的變數,例如const int test; void * ptv; ptv = &test;第三句是非法的,只有將ptv聲明為const void * ptv;,上述第三句ptv = &test才是合法的。
當需要使用通用指針所指的數據參加運算時,需要寫出類型強制轉換。如通用指針ptv 所指空間的數據是整型數據,p是整型指針,用此式轉換:p=(int *)ptv;
G. 資料庫的指針是什麼
資料庫里沒有指針
有游標。
游標是映射在結果集中一行數據上的位置實體,有了游標,用戶就可以訪問結果集中的任意一行數據了,將游標放置到某行後,即可對該行數據進行操作。
1. 聲明游標
CURSOR mycur(vartype number) is
select emp_no,emp_zc from cus_emp_basic
where com_no = vartype;
2. 打開游標
open mycur(000627)
註:000627是參數
3. 讀取數據
fetch mycur into varno, varprice;
4. 關閉游標
close mycur;
H. 什麼是指針
指針是C語言裡面的一個重要概念,也是C語言的難點之一.指針可以表示許多復雜的數據結構,如隊列,棧,鏈表,樹,圖等.
要學習指針,應該先了解以下幾個概念:變數的地址,變數的內容,直接定址,間接定址.
變數的地址:變數在內存中所佔存儲空間的首地址.
變數的內容:變數在內存的存儲單元中存放的數據.
如:
int a=10;//兩個位元組
假設a占的內存單元的地址為:2020和2021
則內存單元的地址為2020的是存放數據a(即10)的低位元組,內存單元的地址為2021的是存放數據a即10)的高位元組.
如果將變數a的首地址2020保存到另一個變數p中,那麼為了訪問變數a,我們可以通過變數p得到a的的地址2020,再到該地址中訪問變數a.
直接定址:直接按變數名來存取變數的內容的訪問方式.
專門用於存放地址型數據的變數是指針變數,如上面所說的p.
間接定址:通過指針變數(如P)間接存取它所指向的變數(如a)的訪問方式稱為間接定址.
在上例中,a的地址用&a表示.由於p是保存地址型數據的,所以p=a的地址=&a
在此p就叫做指針(或指針變數)
其定義如下:
int *p;
指針有好多好處:
1.為函數提供修改變數值的手段.
2.為C的動態內存分配提供支持.
3.為動態數據結構提供支持.
4.可以改善程序的效率.
I. 單片機中程序指針 數據指針 堆棧指針區別
首先,你要明白一個概念,指針,是做什麼的?答案是,指針,是指向地址的。
程序指針,指向的空間,在物理上是Flash,在邏輯上,就是代碼空間。比如說51單片機的PC指針,指向的就是Flash,即程序下一步要執行的指令的地址。
數據指針,指向的空間,在物理上有Flash和RAM,在邏輯上是Flash里的常數空間和數據空間,注意,是對於單片機來說,對於我們的電腦,常數空間不是在Flash上。
比如說51單片機的DPTR,如果用MOVC A,@A+DPTR,此時,就是指向常數空間,如果用
MOVX A,@A+DPTR就是指向的數據空間。
堆棧指針,指向的空間,在物理上是RAM,在邏輯上,就是數據空間,是特定的數據空間,堆棧是數據空間中單獨劃分出來,專門用於寄存中間結果的內存空間。
數據指針和堆棧指針主要有兩個區別:
一是數據指針可以指向Flash,即可以指向常數,比如說我們定義一個數組 unsigned char code Table[99],此時,就是DPTR可以指向常數空間。堆棧指針是不可以的,只能是指向RAM。
第二個區別,堆棧指針指向的是特定的數據空間,這個特定的數據空間,是從整個數據空間里劃分出來,專門用於作堆棧用的,堆棧區間一旦劃分出來,堆棧指針在規則上,就只能在這個范圍內活動,如果出了這個范圍,可能導致整個程序的崩潰。而數據指針在規則上,可以指向整個數據空間,但是,可以讀堆棧空間,不應該去修改,否則也可能導致程序的崩潰。