主頁 > 軟體設計 > 零基礎玩轉C語言系列第七章——初識指標

零基礎玩轉C語言系列第七章——初識指標

2021-12-19 14:37:51 軟體設計

目錄

一、什么是pointer

1.指標理解的兩個要點:

2.指標變數

二、指標型別

三、野指標

1.野指標成因

2.如何避免野指標

四、指標運算

1.指標+-整數

2.指標-指標

3.指標的關系運算

五、二級指標

六、指標陣列


【前言】

指標可以說是C/C++中最難學透的部分了,沒有之一!為了更好地闡述指標的一些重要內容,筆者也是把錄播反復看了好幾遍,才把指標初階整理出來,所以,下面的都是重點哦,還來康康吧,

一、什么是pointer

1.指標理解的兩個要點:

  1. 指標是記憶體中的一個最小記憶體單元的編號,也就是地址(指標就是地址)
  2. 平時我們口語說的指標,通常指的是指標變數是用來存放記憶體地址的變數,

【注意】:記憶體單元 == 編號 == 地址 == 指標

再強調一遍,指標就是地址,通常口語中所說的指標大多指的是指標變數,

在記憶體中:

記憶體被劃分成一個個小的記憶體單元,一個基本的記憶體單元的大小是一個位元組,

2.指標變數

我們可以通過&變數,取出變數的記憶體起始地址,把地址存放到一個變數當中,這個變數就是指標變數,

#include<stdio.h>

int main()
{
	int a = 10;//定義整型變數a,會在記憶體中開辟一塊空間

	int* p = &a;//*告訴我們p是一個指標變數,int表示p指向的物件的資料型別是int

	return 0;

	return 0;
}

指標變數,用來存放地址的變數(注意:存放在指標變數中的值都被當作了地址來處理

那這里的問題是:

  1. 一個小的記憶體單元到底是多大?-->答案是一個位元組
  2. 如何編址呢?

這里就主要探討如何編制:

對于32位機器來說,假設有32根地址線,每根地址線在尋址的時候會產生高電平和低電平,也就是電信號1/0,那么32根地址線產生的地址就會是:

00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010

...      ...      ...      ...


01111111 11111111 11111111 11111111
10000000 00000000 00000000 00000000
10000000 00000000 00000000 00000001

...      ...      ...      ...

11111111 11111111 11111111 11111101
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111

這里就會有2^32個地址編號,因為一個記憶體編號管理一個位元組大小的空間注意這里不要將指標大小和指標管理一塊空間的大小混淆!指標大小在32位平臺是4個位元組,在64位平臺是8個位元組,而指標也就是一塊記憶體單元編號,可以管理一個位元組的空間)所以32位機器可以管理2^32個位元組的記憶體空間,換算成GB也就是:2^32Byte == 2^32 / 1024KB == 2^32 / 1024 / 1024MB == 2^32 / 1024 / 1024 / 1024GB == 4GB,同樣的方法算出,對于64位機器,可以管理8GB大小的記憶體空間,

【總結】

  1. 指標是用來存放地址的,指標是唯一表示一塊記憶體空間的;
  2. 指標的大小在32位平臺是4個位元組,在64位平臺是8個位元組,

二、指標型別

問題引入:指標型別都是4/8個位元組,那還分不同指標型別干什么?

回答這個問題,那這里就要好好說道說道指標型別的意義了(注意哦,非常重要!!!)

意義一:

指標型別決定了指標在解參考的時候一次能訪問幾個位元組(也叫指標的權限),

int* —— 4個位元組

char* —— 1個位元組

double* —— 8個位元組

【注意】:需要注意的是,不要和指標型別的大小混淆咯!

意義二:

指標型別決定了指標向前或向后走一步的步長(+-整數),單位是位元組!

三、野指標

野指標就是指標指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)

1.野指標成因

  1. 指標未初始化;
  2. 指標越界訪問;
  3. 指標指向的空間已經釋放(特別易錯),

具體講解:

<1>指標未初始化

比如:int* p;//區域變數指標未初始化,默認是隨機值,這是不可取的,

<2>指標越界訪問

//最常見的就是陣列越界訪問 
#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int i = 0;
	for (i = 0; i < 12; i++)//陣列越界
	{
		arr[i] = 1;
	}

	return 0;
}

<3>指標指向的空間已經釋放

#include<stdio.h>

int* test()
{
	//區域變數a是具有生命周期的,一旦出了這個范圍就會被銷毀,記憶體空間的使用權限被識訓了
	int a = 100;
	return &a;//回傳a的地址
}

int main()
{
	int* p = test();
	//指標p用來接收a的地址,但是test函式呼叫完畢后,分配給a的記憶體空間也就被識訓了
	//此時p接受的地址是不正確的,導致p成為了野指標
	printf("%d\n", *p);

	return 0;
}

2.如何避免野指標

  1. 指標初始化;
  2. 小心指標越界;
  3. 指標指向的空間釋放需要即時置為NULL(也就是說,指標不想用了就將它置為NULL);
  4. 避免回傳區域變數的地址(野指標的成因3);
  5. 指標使用之前需要檢查其有效性,

具體講解:

<1>指標初始化

比如:int* p = NULL;//指標的使用需要初始化,如果不知道指標指向誰,可以先初始化成NULL

<2>小心指標越界

主要是在陣列中,注意陣列下標很容易導致越界訪問

<3>指標指向的空間釋放需要即時置為NULL(也就是說指標不想用了就將它置為空)

#include<stdio.h>

int main()
{
	int a = 10;
	int* pa = &a;
	//通過指標pa將a的值改為20
	*pa = 20;
	printf("%d\n", a);//輸出20

	//pa完成它的任務之后,在整個工程中都不想用它了,需要即時將它置為NULL
	pa = NULL;//可能在學校教學中很少這樣寫,但是在企業級的代碼規范中是這樣要求的喲
	return 0;
}

<4>避免回傳區域變數的地址

#include<stdio.h>

int* test()
{
	//區域變數a是有生命周期的,所以a一旦出了test()函式范圍就會被銷毀
	//也就是說定義a時分配給a的記憶體空間的使用權限不再是a的了,已經被系統識訓
	int a = 100;
	return &a;//回傳a的地址(出test函式之后這塊地址不再是a的了)
}

int main()
{
	//原本是定義指標變數p,用來接收a的地址
	//但是a呼叫test函式結束后,a的地址被系統識訓了
	//所以指標p指向的位置是不可知的、不正確的
	//這是最容易出錯的典型!一定要小心哦
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

<5>指標使用之前要檢查其有效性

//還用上面的那道題目,通過指標pa將a的值改為20

#include<stdio.h>

int main()
{
	int a = 10;
	int* pa = &a;//此時pa指向的是a的地址,對pa進行解參考操作等同于對a進行操作

	//需要通過對指標pa進行解參考操作,將a的值更改為20
	//但是在使用pa之前,最好要判斷其有效性
	//可能你會覺得下面這個步驟有點畫蛇添足了,但是請相信筆者,這種習慣在上千行的程式中會很受用
	//更不要說在之后進入企業中面對上十萬行的專案了,所以請鐵汁現在就養成良好的編程習慣!
	if (pa != NULL)
	{
		*pa = 20;
	}
	printf("%d\n", a);
	return 0;
}

四、指標運算

1.指標+-整數

這里就要重提指標型別的意義了,前面說過指標型別的意義二:指標型別決定了指標向前或向后走一步的步長(+-整數),單位是位元組,具體看在記憶體中的操作:

#include<stdio.h>

int main()
{
    //定義一個整型陣列
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	
	
	return 0;
}

#include<stdio.h>

int main()
{
    //定義一個字符陣列
	
	char arr[] = {'a','b','c','\0'};
	
	return 0;
}

好,指標+-整數就講到這里咯,大家下去自己動手看看short型、double型指標+-整數是什么樣的效果,

2.指標-指標

注意哦,使用指標-指標運算的時候,前提是兩個指標指向的是同一塊記憶體空間,那何為指向同一塊記憶體空間呢?最典型的例子就是陣列,

指標-指標其實表示的是兩個指標中間的元素個數,注意哦,不是中間有幾個位元組,

指標-指標的實踐:自定義函式實作strlen函式的功能

#include<stdio.h>
#include<assert.h>

int my_strlen(char* arr)
{
	assert(arr);
	char* end = arr;
	while (*end != '\0')
	{
		end++;
	}
	return end - arr;
}

int main()
{
	char arr[] = "abc";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

3.指標的關系運算

指標的關系運算,也就是指標比較大小,指標怎么比較大小呢,前面我們說過,指標就是地址,所以指標比較大小比較的是地址的大小,也就是說比較的是地址的高低,

這個很簡單,在這里就不說了,

五、二級指標

指標變數也是變數,是變數就需要在記憶體中開辟空間,故而也就會有地址,所以指標變數的地址存放到二級指標中,

六、指標陣列

指標陣列是陣列,是用來存放指標變數的陣列! 說簡單點,它和整型陣列、字符陣列等別無二致,只不過陣列型別不同而已,

#include<stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;

	int* pa = &a;
	int* pb = &b;
	int* pc = &c;
    
    //定義一個指標陣列
	int* arr[] = { pa,pb,pc };

	return 0;
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/385889.html

標籤:其他

上一篇:基于VSCode和CMake實作C/C++開發 | Linux篇

下一篇:STM32---串口實作在應用程式的韌體更新(IAP)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more