指針的使用

来源:http://www.cnblogs.com/OctoptusLian/archive/2017/07/11/7152264.html
-Advertisement-
Play Games

指針的語法 聲明一個指針變數的語法: <type> *<ptr_name>; 註:該語法不僅僅指出一個變數為指針,同時表明指針所指向的記憶體的類型。 指針的指向:變數的地址 指針既可以直接指向新分配的記憶體,也可以指向一個已經存在的變數。 為了獲得變數地址(即變數在記憶體中的位置),要把符號&放在變數名前 ...


指針的語法

聲明一個指針變數的語法:

<type>  *<ptr_name>;

註:該語法不僅僅指出一個變數為指針,同時表明指針所指向的記憶體的類型。

 

指針的指向:變數的地址

指針既可以直接指向新分配的記憶體,也可以指向一個已經存在的變數。

為了獲得變數地址(即變數在記憶體中的位置),要把符號&放在變數名前。&稱為取地址操作符,因為它能返回變數的記憶體地址:

    int x;
    int *p_x = &x;
    *p_x = 2;
    cout << x << endl;  //輸出x的值等於2

 

&的作用是得到變數的地址。

(記憶方法:字元“&”的單詞 ampersand 和“地址” address 都是以 a 打頭的,使用&符號就像是通過網站的地址欄獲得該網站的URL)

 

指針的使用通常可以用來做下列兩件事:

  • 獲得指針中存儲的記憶體地址;
  • 獲得記憶體單元中存儲的值。

例如,輸出指針 p_pointer_to_integer 指向(存儲)的地址:

    int x = 5;
    int *p_pointer_to_integer = &x;
    cout << p_pointer_to_integer;  //輸出x的地址
    //等價於 cout << &x

 

 

這個代碼片段列印輸出變數x的記憶體地址,而這個變數存儲在 p_pointer_to_integer 中。

 

如果要訪問記憶體單元中存儲的值,可以使用 操作符,例如:

    int x = 5;
    int *p_pointer_to_integer = &x;
    cout << *p_pointer_to_integer;  //輸出5
    //等價於 cout << x

 

代碼 *p_pointer_to_integer 表示“到指針所指向的記憶體,去取出存儲在裡面的值”。在這個例子中,指針 *p_pointer_to_integer 指向了變數x,而x的值是5,所以輸出了數值5。

 

使用*來獲得指針變數指向的地址的值,這一過程稱為間接引用指針(為了獲得地址中存儲的值,我們是通過一個到該記憶體地址的引用,使用它,間接地到達目的地)。

通過間接引用指針,還可以修改指針地址所指向的變數的值,例如:

    int x;
    int *p_pointer_to_integer = &x;
    *p_pointer_to_integer = 5;  //x的值現在修改為5
    cout << x;  //輸出5

 

 

那麼,什麼時候應該在變數名前加上*號(或&號)?這個很容易出錯,為此整理了一下,如下表所示:

操作目的

需要的操作符

示例

聲明指針

*

Int *p_x

獲得指針所指向的地址

不需要

Cout << p_x

調整指針所指向的地址

不需要

Int *p_x; p_x = /*address*/

獲得指針所指向的地址中的值

*

Cout << *p_x

調整指針所指向的地址中的值

*

*p_x = 5;

聲明變數

不需要

Int y;

獲得變數的值

不需要

Int y; cout << y;

調整變數的值

不需要

Int y; y=5;

獲得變數的地址

&

Int y; int *p_x; p_x = &y;

調整變數的地址

不可行

不可以,變數地址不能更改

 

要記住這張表,切記兩個規則:

  • 指針存儲的是地址。因此,直接使用“裸”指針(即不帶任何符號的指針)得到的就是地址。要獲得或調整存儲在該地址中的值,必須添加額外的*。
  • 變數存儲的是數據值。因此,直接使用變數得到的就是數據值。而要獲得變數的地址,就必須額外添加&。

 

現在,我們通過一個簡單的程式來演示下這些功能:

#include <iostream>

using namespace std;

int main()
{
    int x;  //x為普通變數
    int *p_int;  //p_int為指向一個整型數的指針

    p_int = &x;  //將x的地址賦值給p_int
    cout << "Please enter a number: ";
    cin >> x;  //讀入一個值並賦給變數x,這裡的x也可以用*p_int來代替
    cout << *p_int << '\n';  //使用*來獲得指針所指向的變數的值
    *p_int = 10;
    cout << x;  //再次輸出10
}

 

 

第一個cout輸出變數x的值。讓我們來逐步地執行程式,觀察記憶體是怎樣變化的。我們用箭頭來表示指針指向的位置,方框中的數字表示非指針變數在記憶體中的值。

(1)剛開始,我們有一個整型變數x,以及一個指向整型的指針變數p_int。直觀上,可以認為現在有兩個值未知的變數:

 

(2)接著,代碼通過使用取地址符(&)獲得變數x的地址,並將該地址存儲到指針p_int 中。

    p_int = &x;  //將x的地址賦值給p_int

 

因此,我們可以畫一條從變數p_int到變數x的箭頭,表示指針p_int指向變數x。

 

(3)然後用戶輸入一個數字,存儲在變數x中,該存儲位置也是p_int所指向的位置。

    cin >> x;  //讀入一個值並賦給變數x,這裡的x也可以用*p_int來代替

 

簡單起見,我們假設用戶輸入數字5.現在記憶體的情況變成了這樣:

 

(4)接著,下一行代碼將*p_int傳給cout。p_int間接引用了p_int,它會檢查p_int中的地址,並且到該地址中取出其變數值。

    cout << *p_int << '\n';  //使用*來獲得指針所指向的變數的值

 

 

(5)最後的兩行語句錶面,通過指針可以修改變數原來的值。這個語句將值10存儲到p_int所指向的記憶體中,也就是存儲著變數x的值的記憶體。

    *p_int = 10;

 

 總結

 在學習數據結構的時候,發現對指針這塊還是有些模糊,於是回顧了一下指針,將其收穫和感受寫了下來。

此次學習使我瞭解了使用指針的好處之一就是方便修改其所指向記憶體的值;清楚了什麼時候應該在變數名前加上*號(或&號);當搞不明白使用指針時記憶體的變化過程時,可以先繪製出記憶體的初始狀態,配合箭頭圖逐步執行程式,記憶體的變化過程也就一目瞭然了,每當指針的指向改變時,便繪製新的箭頭,每當變數的值發生變化時,更新它的值。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用java8 的lanmbe表達式時,使用java1.8編譯,則會報錯需要在pom.xml的中添加 org.apache.maven.plugins maven-compiler-plugin 2.3.2 ... ...
  • 前提: python3.4 windows 作用:通過搜狗的微信搜索介面http://weixin.sogou.com/來搜索相關微信文章,並將標題及相關鏈接導入Excel表格中 說明:需xlsxwriter模塊,另程式編寫時間為2017/7/11,以免之後程式無法使用可能是網站做過相關改變,程式較 ...
  • 題目描述 墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你需要回答墨墨的提問。墨墨會像你發佈如下指令: 1、 Q L R代表詢問你從第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。 2、 R P Col 把第P支畫筆替換為顏色Col。 為了滿足墨墨的要求,你知道你需要乾什麼了嗎? 輸 ...
  • 在自學到java面向對象時,知道有靜態代碼塊,構造代碼塊和構造函數的存在,如果說構造函數是初始化對象,那麼其他2者又是怎麼使用,又有什麼區別呢。簡單的舉了下麵的例子: 列印的結果為 所以可以看出先後順序為靜態代碼塊,構造代碼塊,構造函數。 其中靜態代碼塊只隨著類的載入載入一次,一般就用於初始化類。 ...
  • 一、創建基於ThreadLocal的動態數據源容器,保證數據源的線程安全性 二、定義Spring動態數據源擴展類,用來實現Master、Slave數據源動態切換 三、配置Master、Slave數據源 1. db.properties配置Master、Slave數據信息 # Master DB db ...
  • 計算工齡原則:若是2000-10-12作為開始工作時間,則到下一年的2001-10-13算為一年。有個bug,不滿一年的工齡是錯誤的。import java.util.Date;import java.util.Calendar; public int workAge(Date nowTime, D ...
  • 在實際項目中時常需要連接多個資料庫,而且不同的業務需求在實現過程當中往往需要訪問不同的資料庫。 jdbc.properties配置文件,配置多個dataSource spring-config.xml配置文件如下,將DynamicDataSource Bean加入到Spring的上下文xml配置文件 ...
  • STL記憶體空間的配置/釋放與對象內容的構造/析構,是分開進行的。 對象的構造、析構 對象的構造由construct函數完成,該函數內部調用定位new運算符,在指定的記憶體位置構造對象。如下: template <typename T1, typename T2> inline void constru ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...