C++編程中指針的聲明與根本應用講授。本站提示廣大學習愛好者:(C++編程中指針的聲明與根本應用講授)文章只能為提供參考,不一定能成為您想要的結果。以下是C++編程中指針的聲明與根本應用講授正文
應用以下序列聲明指針。
[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] declarator ;
個中,任何有用指針聲明符都可用於 declarator。簡略指針聲明符的語法以下所示:
* [cv-qualifiers] identifier [= expression]
1.聲明解釋符:
可選存儲類解釋符。
運用於要指向的對象的類型的可選 const 或 volatile 症結字。
類型解釋符:可表現要指向的對象的類型的類型稱號。
2.聲明符:
可選的 Microsoft 公用潤飾符。
* 運算符。
運用於指針自己的可選 const 或 volatile 症結字。
標識符。
可選初始值設定項。
指向函數的指針的聲明符相似於以下情勢:
(* [cv-qualifiers] identifier )( argument-list ) [cv-qualifers] [exception specification] [= expression];
關於指針數組,語法以下所示:
* identifier [ [ constant-expression ] ]
然則,指針聲明符能夠更龐雜。
多個聲明符及其初始值設定項能夠同時湧現在後面有聲明解釋符且以逗號分隔的列表中的一個聲明中。
指針聲明的簡略示例以下:
char *pch;
後面的聲明指定 pch 指向 char 類型的對象。
更龐雜的示例是
static unsigned int * const ptr;
後面的聲明指定 ptr 是一個指向 unsigned int 類型(帶靜態存儲連續時光)的對象的常量指針。
下一個示例演示若何聲明和初始化多個指針:
static int *p = &i, *q = &j;
在後面的示例中,指針 p 和 q 都指向類型 int 的對象並分離初始化為 i 和 j 的地址。存儲類解釋符 static 運用於這兩個指針。
// 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
另外一個示例演示若何在數據構造中應用指針;本例中采取鏈接列表。
// 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 症結字用於更改處置指針的方法。 const 症結字指定指針在初始化後沒法修正;爾後指針將遭到掩護,避免停止修正。
volatile 症結字指定與後跟的稱號聯系關系的值可由用戶運用法式中的操作之外的操作修正。是以,volatile 症結字關於聲明同享內存中可由多個過程拜訪的對象或用於與中止辦事例程通訊的全局數據區域很有效。
假如某個稱號被聲明為 volatile,則每當法式拜訪該稱號時,編譯器都邑從新加載內存中的值。這將明顯削減能夠的優化。然則,當對象的狀況能夠不測更改時,這是包管可預感的法式機能的獨一辦法。
若要將指針指向的對象聲明為 const 或 volatile,請應用以下情勢的聲明:
const char *cpch; volatile char *vpch;
若要將指針的值(即指針中存儲的現實地址)聲明為 const 或 volatile,請應用以下情勢的聲明:
char * const pchc; char * volatile pchv;
C++ 說話會阻攔將許可修正聲明為 const 的對象或指針的賦值。此類賦值會移除用來聲明對象或指針的信息,從而違背原始聲明的意圖。請斟酌以下聲明:
const char cch = 'A'; char ch = 'B';
假定後面聲清楚明了兩個對象(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;
以下聲明/初始化存在毛病。
char *pch2 = &cch; // Error char *const pch3 = &cch; // Error
pch2 的聲明聲清楚明了一個可以用來修正常量對象的指針,是以不許可應用。 pch3 的聲明指定 pointer 是常量,而不是對象;與不許可應用 pch2 的緣由雷同,也不許可應用該聲明。
以下八個賦值顯示了經由過程指針停止的賦值和對後面的聲明的指針值的更改;如今,假定 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 的組合的指針遵守雷同的規矩。
指向 const 對象的指針平日用於函數聲明中,以下所示:
errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );
後面的語句聲清楚明了函數 strcpy_s,個中,三個參數中的兩個是指向 char 的類型指針。因為參數是按援用而不是按值傳遞的,是以,假如未將 strSource 聲明為 const,則該函數可以自在修正 strDestination 和 strSource。將 strSource 聲明為 const 可向挪用方包管挪用的函數沒法更改 strSource。
留意
因為存在從 typename * 到 const typename * 的尺度轉換,是以將 char * 類型的參數傳遞到 strcpy_s 是正當的。然則,反之則不可;不存在從對象或指針中移除 const 特征的隱式轉換。
給定類型的 const 指針可以分派給統一類型的指針。然則,非 const 類型的指針不克不及賦給 const 指針。以下代碼顯示了准確和毛病的賦值:
// const_pointer.cpp int *const cpObject = 0; int *pObject; int main() { pObject = cpObject; cpObject = pObject; // C3892 }
以下示例顯示了當有指針指向某個指向對象的指針時若何將對象聲明為 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; }