欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++編程中指針的聲明與基本使用講解

 更新時(shí)間:2016年01月25日 16:10:07   投稿:goldensun  
這篇文章主要介紹了詳解C++編程中C++編程中指針的聲明與基本使用講解,文中舉了簡(jiǎn)單的例子來講如何在基本的數(shù)據(jù)結(jié)構(gòu)中使用指針,以及固定和可變指針的介紹,需要的朋友可以參考下

使用以下序列聲明指針。

[storage-class-specifiers] [cv-qualifiers] type-specifiers 
[ms-modifier] declarator ;

其中,任何有效指針聲明符均可用于 declarator。簡(jiǎn)單指針聲明符的語(yǔ)法如下所示:

* [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ù)組,語(yǔ)法如下所示:

* identifier [ [ constant-expression ] ]

但是,指針聲明符可能更復(fù)雜。
多個(gè)聲明符及其初始值設(shè)定項(xiàng)可能同時(shí)出現(xiàn)在前面有聲明說明符且以逗號(hào)分隔的列表中的一個(gè)聲明中。
指針聲明的簡(jiǎn)單示例如下:

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++ 語(yǔ)言會(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 );

前面的語(yǔ)句聲明了函數(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;
}

相關(guān)文章

  • Qt TCP實(shí)現(xiàn)簡(jiǎn)單通信功能

    Qt TCP實(shí)現(xiàn)簡(jiǎn)單通信功能

    這篇文章主要為大家詳細(xì)介紹了Qt TCP實(shí)現(xiàn)簡(jiǎn)單通信功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法

    error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法

    error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法,需要的朋友可以參考一下
    2013-05-05
  • C語(yǔ)言實(shí)現(xiàn)隨機(jī)抽取紙牌程序

    C語(yǔ)言實(shí)現(xiàn)隨機(jī)抽取紙牌程序

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)隨機(jī)抽取紙牌程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Qt控件之QLabel用法及技巧

    Qt控件之QLabel用法及技巧

    QLabel是Qt中的一個(gè)控件類,用于顯示文本或圖像的控件類之一,本文主要介紹了Qt控件之QLabel用法及技巧,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • c++11新特性多線程操作實(shí)戰(zhàn)

    c++11新特性多線程操作實(shí)戰(zhàn)

    這篇文章主要介紹了c++11新特性多線程操作實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • C++基于easyx圖形庫(kù)實(shí)現(xiàn)打磚塊游戲

    C++基于easyx圖形庫(kù)實(shí)現(xiàn)打磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了C++基于easyx圖形庫(kù)實(shí)現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C/C++?Qt?數(shù)據(jù)庫(kù)QSql增刪改查組件應(yīng)用教程

    C/C++?Qt?數(shù)據(jù)庫(kù)QSql增刪改查組件應(yīng)用教程

    Qt?SQL模塊是Qt中用來操作數(shù)據(jù)庫(kù)的類,該類封裝了各種SQL數(shù)據(jù)庫(kù)接口,可以很方便的鏈接并使用。本文主要介紹了Qt數(shù)據(jù)庫(kù)QSql增刪改查組件的應(yīng)用教程,感興趣的同學(xué)可以學(xué)習(xí)一下
    2021-12-12
  • C++十六進(jìn)制宏的用法詳解

    C++十六進(jìn)制宏的用法詳解

    C++十六進(jìn)制宏的用法;本文將詳細(xì)介紹
    2012-11-11
  • C語(yǔ)言安全編碼之?dāng)?shù)組索引位的合法范圍

    C語(yǔ)言安全編碼之?dāng)?shù)組索引位的合法范圍

    這篇文章主要介紹了C語(yǔ)言安全編碼的數(shù)組索引位合法范圍剖析,對(duì)于編碼安全非常重要!需要的朋友可以參考下
    2014-07-07
  • c/c++實(shí)現(xiàn)獲取域名的IP地址

    c/c++實(shí)現(xiàn)獲取域名的IP地址

    本文給大家匯總介紹了使用c/c++實(shí)現(xiàn)獲取域名的IP地址的幾種方法以及這些方法的核心函數(shù)gethostbyname的詳細(xì)用法,非常的實(shí)用,有需要的小伙伴可以參考下。
    2015-11-11

最新評(píng)論