編程練習之數組與指針

来源:http://www.cnblogs.com/PROJECT-IDOLPROGRAM/archive/2016/01/03/5097344.html
-Advertisement-
Play Games

數組與指針閱讀如下代碼,為何出錯。 1 int main() { 2 char a[] = { "I am a bad boy" }; 3 char * pA = new char[ sizeof( a ) ]; 4 pA = a; 5 6 ...


數組與指針

閱讀如下代碼,為何出錯。

 1 int main() {  
 2     char a[] = { "I am a bad boy" };  
 3     char * pA = new char[ sizeof( a ) ];  
 4     pA = a;  
 5       
 6     for ( size_t i = 0; i < sizeof( a ); ++i ) {  
 7         std::cout << *pA << std::endl;  
 8         ++pA;  
 9     }  
10     delete [] pA;  
11     pA = NULL;  
12     return 0;  
13 }

我們把那段魔術字元串命名為x。

第一步我們將字元串x存入了棧空間;第二步我們試圖在堆空間申請一塊可以正好存放x的的記憶體。以上兩步都做得很對,但第三步大有問題。

本意是企圖將x複製入堆記憶體中,但實際操作的結果是將指針指向了原x所在的棧空間。這將導致一個記憶體泄漏。(要註意的是string類的等於號能夠賦值是因為操作符的重載)。接下來是遍歷整個字元串,運行結果仿佛複製成功了一樣,但實際上你是在遍歷存在於棧空間的x。遍歷的過程中還不斷修改指針指向的值,因為分配字元串時最後會自動添加一個空字元串(等價於NULL或0),指針最終指向了棧空間的x末尾的空字元串處。企圖釋放棧空間導致的爆炸就更不用說了。

 

代碼如何修改才正確呢?

 1 int main() {  
 2     char a[] = { "I am a bad boy" };  
 3     char * pA = new char[ sizeof( a ) ]; 
 4     strcpy( pA, a );    
 5     for ( size_t i = 0; i < sizeof( a ); ++i ) {  
 6         std::cout << *( pA + i );  
 7     }  
 8     delete [] pA;  
 9     pA = NULL;  
10     return 0;  
11 }  

將字元串拷貝到堆記憶體分配的空間中,需要用到c函數strcpy,將值拷貝過去。你也可以將x的每一個字元賦值過去。註意,千萬儘量不要改變指向堆記憶體首個位置的指針,如果你有把握還原回去的話。釋放一定要從堆記憶體首部分開始,不然也會導致爆炸。

 

期間你有可能會忽略這些問題。

(1)

1 ++pA;

上面已經提到過了,沒有把握釋放的是首位的話儘量不要改變指針的指向。你可以使用指針的偏移或數組下標來進行操作

(2)

1 char * pA = new char[ strlen( a ) ]; 

要註意strlen不計空字元的,因此堆記憶體分配時中會少一個存放空字元的空間,導致很多函數不能在這段字元結束時停止讀取。

1 char * pA = new char[ strlen( a ) + 1 ]; 

多分配一個即可,或你可以使用sizeof(註意 sizeof 指向堆記憶體指針 為指針的大小)。

(3)

你可能會這樣釋放數組堆記憶體。

1 delete pA;  

編譯運行,沒有任何問題。但這是一個未定義行為(UB),在不同的平臺或編譯器下運行結果可能不同,總之這是一個潛在的危險操作,你應該讓自己嚴格使用delete[]去釋放數組堆記憶體。

 

後記:

提到了string重載的等號。對於熟悉C/C++的人在這方面不會有任何問題,但對於初學者這可能確實不太好理解和弄懂。我一直不使用重載操作符或許和這也有關係吧。


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

-Advertisement-
Play Games
更多相關文章
  • 從零到千萬,伺服器的架構怎麼變?泣血乾貨集。長文,慎入。
  • 移動開發者面臨的技術挑戰 初創期 創意->客戶端開發->服務端開發->測試 技術選型: 開發語言 技術框架 雲計算 圖片 資料庫 緩存 中間件 大數據計算 架構穩定:有靈活性和可擴展性,架構清晰,新人可以快速上手。 上升期 運維挑戰: ü 部署發佈不成為難點 ü 加機器,怎麼加? ü 數據的備...
  • 意圖 0 適用性 1 結構 2 實現 3 效果 4 參考 5意圖使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。適用性在以下條件下使用:有多個對象可以處理一個請求,哪個對象處理該請求運行時刻...
  • 怎樣寫出高逼格的計算器(用上封裝、繼承、多態) -- 簡單工廠模式
  • 回到目錄Lind.DDD.Repositories.EF以下簡稱Repositories.EF,之所以把它從Lind.DDD中拿出來,完全出於可插拔的考慮,讓大家都能休會到IoC的魅力,用到哪種方法持久化,就將那個DLL放到應用程式中,完全不需要把所有持久化方式耦合到一個項目里,這也是遵循了OCP的...
  • 回到目錄Lind.DDD.Domain位於Lind.DDD核心項目中,它主要面向領域實體而設計,由一個IEntity的標識介面,EntityBase基類和N個Entity實體類組成,其中IEntity主要用來標識,在倉儲操作時,用它來表明操作的實體範圍和約束;EntityBase定義了幾個公用的屬性...
  • hi懶癌是最可怕的癌了吧,在即將迎來本命年時,給自己定下每天必乾的幾件成習慣的事情,望不再鴿!!php是我一直在學習的東西,但總以為php簡單,難點在需要掌握大量的相關知識,其實並不完全對,php也是有演算法好吧,php也值得認真對待,既然決定學了,拿點樣子出來啊,是男人吧。1、PHP一、PHP基.....
  • 1 package com.test; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputSt.....
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...