C++編程中指針的聲明與基本使用講解
使用以下序列聲明指針。
[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] declarator ;
其中,任何有效指針聲明符均可用于 declarator。簡單指針聲明符的語法如下所示:
* [cv-qualifiers] identifier [= expression]
1.聲明說明符:
可選存儲(chǔ)類說明符。
應(yīng)用于要指向的對(duì)象的類型的可選 const 或 volatile 關(guān)鍵字。
類型說明符:可表示要指向的對(duì)象的類型的類型名稱。
2.聲明符:
可選的 Microsoft 專用修飾符。
* 運(yùn)算符。
應(yīng)用于指針本身的可選 const 或 volatile 關(guān)鍵字。
標(biāo)識(shí)符。
可選初始值設(shè)定項(xiàng)。
指向函數(shù)的指針的聲明符類似于以下形式:
(* [cv-qualifiers] identifier )( argument-list ) [cv-qualifers] [exception specification] [= expression];
對(duì)于指針數(shù)組,語法如下所示:
* identifier [ [ constant-expression ] ]
但是,指針聲明符可能更復(fù)雜。
多個(gè)聲明符及其初始值設(shè)定項(xiàng)可能同時(shí)出現(xiàn)在前面有聲明說明符且以逗號(hào)分隔的列表中的一個(gè)聲明中。
指針聲明的簡單示例如下:
char *pch;
前面的聲明指定 pch 指向 char 類型的對(duì)象。
更復(fù)雜的示例是
static unsigned int * const ptr;
前面的聲明指定 ptr 是一個(gè)指向 unsigned int 類型(帶靜態(tài)存儲(chǔ)持續(xù)時(shí)間)的對(duì)象的常量指針。
下一個(gè)示例演示如何聲明和初始化多個(gè)指針:
static int *p = &i, *q = &j;
在前面的示例中,指針 p 和 q 都指向類型 int 的對(duì)象并分別初始化為 i 和 j 的地址。存儲(chǔ)類說明符 static 應(yīng)用于這兩個(gè)指針。
// pointer.cpp
// compile with: /EHsc
#include <iostream>
int main() {
int i = 1, j = 2; // local variables on the stack
int *p;
// a pointer may be assigned to "point to" the value of
// another variable using the & (address of) operator
p = & j;
// since j was on the stack, this address will be somewhere
// on the stack. Pointers are printed in hex format using
// %p and conventionally marked with 0x.
printf_s("0x%p\n", p);
// The * (indirection operator) can be read as "the value
// pointed to by".
// Since p is pointing to j, this should print "2"
printf_s("0x%p %d\n", p, *p);
// changing j will change the result of the indirection
// operator on p.
j = 7;
printf_s("0x%p %d\n", p, *p );
// The value of j can also be changed through the pointer
// by making an assignment to the dereferenced pointer
*p = 10;
printf_s("j is %d\n", j); // j is now 10
// allocate memory on the heap for an integer,
// initialize to 5
p = new int(5);
// print the pointer and the object pointed to
// the address will be somewhere on the heap
printf_s("0x%p %d\n", p, *p);
// free the memory pointed to by p
delete p;
// At this point, dereferencing p with *p would trigger
// a runtime access violation.
// Pointer arithmetic may be done with an array declared
// on the stack or allocated on the heap with new.
// The increment operator takes into account the size
// of the objects pointed to.
p = new int[5];
for (i = 0; i < 5; i++, p++) {
*p = i * 10;
printf_s("0x%p %d\n", p, *p);
}
// A common expression seen is dereferencing in combination
// with increment or decrement operators, as shown here.
// The indirection operator * takes precedence over the
// increment operator ++.
// These are particularly useful in manipulating char arrays.
char s1[4] = "cat";
char s2[4] = "dog";
char* p1 = s1;
char* p2 = s2;
// the following is a string copy operation
while (*p1++ = *p2++);
// s2 was copied into s1, so now they are both equal to "dog"
printf_s("%s %s", s1, s2);
}
輸出:
0x0012FEC8 0x0012FEC8 2 0x0012FEC8 7 j is 10 0x00320850 5 0x00320850 0 0x00320854 10 0x00320858 20 0x0032085C 30 0x00320860 40 dog dog
另一個(gè)示例演示如何在數(shù)據(jù)結(jié)構(gòu)中使用指針;本例中采用鏈接列表。
// pointer_linkedlist.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct NewNode {
NewNode() : node(0){}
int i;
NewNode * node;
};
void WalkList(NewNode * ptr) {
if (ptr != 0) {
int i = 1;
while (ptr->node != 0 ) {
cout << "node " << i++ << " = " << ptr->i << endl;
ptr = ptr->node;
}
cout << "node " << i++ << " = " << ptr->i << endl;
}
}
void AddNode(NewNode ** ptr) {
NewNode * walker = 0;
NewNode * MyNewNode = new NewNode;
cout << "enter a number: " << endl;
cin >> MyNewNode->i;
if (*ptr == 0)
*ptr = MyNewNode;
else {
walker = *ptr;
while (walker->node != 0)
walker = walker->node;
walker->node = MyNewNode;
}
}
int main() {
char ans = ' ';
NewNode * ptr = 0;
do {
cout << "a (add node) d (display list) q (quit)" << endl;
cin >> ans;
switch (ans) {
case 'a':
AddNode(&ptr);
break;
case 'd':
WalkList(ptr);
break;
}
} while (ans != 'q');
}
輸出:
a 45 d a 789 d qa (add node) d (display list) q (quit) enter a number: a (add node) d (display list) q (quit) node 1 = 45 a (add node) d (display list) q (quit) enter a number: a (add node) d (display list) q (quit) node 1 = 45 node 2 = 789 a (add node) d (display list) q (quit)
固定和可變指針
const 和 volatile 關(guān)鍵字用于更改處理指針的方式。 const 關(guān)鍵字指定指針在初始化后無法修改;此后指針將受到保護(hù),防止進(jìn)行修改。
volatile 關(guān)鍵字指定與后跟的名稱關(guān)聯(lián)的值可由用戶應(yīng)用程序中的操作以外的操作修改。因此,volatile 關(guān)鍵字對(duì)于聲明共享內(nèi)存中可由多個(gè)進(jìn)程訪問的對(duì)象或用于與中斷服務(wù)例程通信的全局?jǐn)?shù)據(jù)區(qū)域很有用。
如果某個(gè)名稱被聲明為 volatile,則每當(dāng)程序訪問該名稱時(shí),編譯器都會(huì)重新加載內(nèi)存中的值。這將顯著減少可能的優(yōu)化。但是,當(dāng)對(duì)象的狀態(tài)可能意外更改時(shí),這是保證可預(yù)見的程序性能的唯一方法。
若要將指針指向的對(duì)象聲明為 const 或 volatile,請(qǐng)使用以下形式的聲明:
const char *cpch; volatile char *vpch;
若要將指針的值(即指針中存儲(chǔ)的實(shí)際地址)聲明為 const 或 volatile,請(qǐng)使用以下形式的聲明:
char * const pchc; char * volatile pchv;
C++ 語言會(huì)阻止將允許修改聲明為 const 的對(duì)象或指針的賦值。此類賦值會(huì)移除用來聲明對(duì)象或指針的信息,從而違反原始聲明的意圖。請(qǐng)考慮以下聲明:
const char cch = 'A'; char ch = 'B';
假定前面聲明了兩個(gè)對(duì)象(const char 類型的 cch 和 char 類型的 ch),以下聲明/初始化將是有效的:
const char *pch1 = &cch; const char *const pch4 = &cch; const char *pch5 = &ch; char *pch6 = &ch; char *const pch7 = &ch; const char *const pch8 = &ch;
以下聲明/初始化存在錯(cuò)誤。
char *pch2 = &cch; // Error char *const pch3 = &cch; // Error
pch2 的聲明聲明了一個(gè)可以用來修改常量對(duì)象的指針,因此不允許使用。 pch3 的聲明指定 pointer 是常量,而不是對(duì)象;與不允許使用 pch2 的原因相同,也不允許使用該聲明。
以下八個(gè)賦值顯示了通過指針進(jìn)行的賦值以及對(duì)前面的聲明的指針值的更改;現(xiàn)在,假設(shè) pch1 到 pch8 的初始化是正確的。
*pch1 = 'A'; // Error: object declared const pch1 = &ch; // OK: pointer not declared const *pch2 = 'A'; // OK: normal pointer pch2 = &ch; // OK: normal pointer *pch3 = 'A'; // OK: object not declared const pch3 = &ch; // Error: pointer declared const *pch4 = 'A'; // Error: object declared const pch4 = &ch; // Error: pointer declared const
聲明為 volatile 或 const 和 volatile 的組合的指針遵循相同的規(guī)則。
指向 const 對(duì)象的指針通常用于函數(shù)聲明中,如下所示:
errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );
前面的語句聲明了函數(shù) strcpy_s,其中,三個(gè)參數(shù)中的兩個(gè)是指向 char 的類型指針。由于參數(shù)是按引用而不是按值傳遞的,因此,如果未將 strSource 聲明為 const,則該函數(shù)可以自由修改 strDestination 和 strSource。將 strSource 聲明為 const 可向調(diào)用方保證調(diào)用的函數(shù)無法更改 strSource。
注意
由于存在從 typename * 到 const typename * 的標(biāo)準(zhǔn)轉(zhuǎn)換,因此將 char * 類型的參數(shù)傳遞到 strcpy_s 是合法的。但是,反之則不行;不存在從對(duì)象或指針中移除 const 特性的隱式轉(zhuǎn)換。
給定類型的 const 指針可以分配給同一類型的指針。但是,非 const 類型的指針不能賦給 const 指針。以下代碼顯示了正確和錯(cuò)誤的賦值:
// const_pointer.cpp
int *const cpObject = 0;
int *pObject;
int main() {
pObject = cpObject;
cpObject = pObject; // C3892
}
以下示例顯示了當(dāng)有指針指向某個(gè)指向?qū)ο蟮闹羔槙r(shí)如何將對(duì)象聲明為 const。
// const_pointer2.cpp
struct X {
X(int i) : m_i(i) { }
int m_i;
};
int main() {
// correct
const X cx(10);
const X * pcx = &cx;
const X ** ppcx = &pcx;
// also correct
X const cx2(20);
X const * pcx2 = &cx2;
X const ** ppcx2 = &pcx2;
}
上一篇:Linux下C語言實(shí)現(xiàn)C/S模式編程
欄 目:C語言
下一篇:了解C++編程中指定的異常和未經(jīng)處理的異常
本文標(biāo)題:C++編程中指針的聲明與基本使用講解
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2519.html
您可能感興趣的文章
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)數(shù)怎么表達(dá)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10delphi制作wav文件的方法


