最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++數(shù)組和數(shù)組名問題(指針、解引用)

 更新時(shí)間:2021年09月18日 12:06:49   作者:IE貓  
這篇文章主要介紹了詳解C++數(shù)組和數(shù)組名問題(指針、解引用),指針的實(shí)質(zhì)就是個(gè)變量,它跟普通變量沒有任何本質(zhì)區(qū)別,指針本身是一個(gè)對象,同時(shí)指針無需在定義的時(shí)候賦值,具體內(nèi)容詳情跟隨小編一起看看吧

一、指針

 1.1 指針變量和普通變量的區(qū)別

指針:指針的實(shí)質(zhì)就是個(gè)變量,它跟普通變量沒有任何本質(zhì)區(qū)別。指針完整的應(yīng)該叫指針變量,簡稱為指針。 是指向的意思。指針本身是一個(gè)對象,同時(shí)指針無需在定義的時(shí)候賦值。

1.2 為什么需要指針

指針的出現(xiàn)是為了實(shí)現(xiàn)間接訪問。在匯編中都有間接訪問,其實(shí)就是CPU的尋址方式中的間接上。

間接訪問(CPU的間接尋 址)是CPU設(shè)計(jì)時(shí)決定的,這個(gè)決定了匯編語言必須能夠?qū)崿F(xiàn)問接尋又決定了匯編之上的C語言也必須實(shí)現(xiàn)簡介尋址。

1.3 指針使用三部曲

三部曲:定義指針變量、關(guān)聯(lián)指針變量、解引用

(1)當(dāng)我們int *p定義一個(gè)指針變量p時(shí),因?yàn)閜是局部變量,所以也道循C語言局部變量的一般規(guī)律(定義局部變量并且未初始化,則值是隨機(jī)的),所以此時(shí)p變量中存儲(chǔ)的是一個(gè)隨機(jī)的數(shù)字。

(2)此時(shí)如果我們解引用p,則相當(dāng)于我們訪問了這個(gè)隨機(jī)數(shù)字為地址的內(nèi)存空間。那這個(gè)空間到底能不能訪問不知道(也許行也許不行),所以如果直接定義指針變量未綁定有效地址就去解引用幾平必死無疑。

(3)定義一個(gè)指針變量,不經(jīng)綁定有效地址就去解引用,就好象拿一個(gè)上了鏜的槍隨意轉(zhuǎn)了幾圈然后開了槍。

(4)指針綁定的意義就在于讓指針指向一個(gè)可以訪問、應(yīng)該訪問的地方(就好象拿著槍瞄準(zhǔn)且標(biāo)的過程一樣),指針的解引用是為了間接訪問目標(biāo)變量(就好象開槍是為了打中目標(biāo)一樣)

int val = 43;
int * p = &val;   // &在右值為取值符
cout << *p << endl;

//輸出
43

二、整形、浮點(diǎn)型數(shù)組

 前言

  • 在很多用到數(shù)組名字的地方,編譯器都會(huì)自動(dòng)地將其替換為一個(gè)指向該數(shù)組首元素的指針。
  • 所以,在大多數(shù)表達(dá)式中,使用數(shù)組名其實(shí)是在使用一個(gè)指向該數(shù)組首元素的指針。

2.1 數(shù)組名其實(shí)是特殊的指針

int main()
{
	int a[] = { 0,1,2,3,4 };
	printf("%x\n", a);
	printf("%x\n", &a);
	printf("%x\n", &a[0]);
}

在這里插入圖片描述

  • 從局部變量表可以看出,數(shù)組a和指針p的構(gòu)成是很相似的。它們實(shí)際存的都是一個(gè)地址,都會(huì)指向一個(gè)對象(或多個(gè)對象的第一個(gè)對象)。所以說數(shù)組名其實(shí)是種特殊的指針。
  • 為什么說是特殊呢?

一維數(shù)組

 int a[] = { 0,1,2,3,4 };
    int * p1 = a;
    int *p = &a[0];
    //指針p是 int * 的,而首元素是有地址的,所以取址,是允許的
    
	//int * p1 = &a;    //錯(cuò)誤
	//理解:int (*p1)[5] = &a;  //正確
	/*
	但它倆自身又有不同:
	指針 p1 本身是一個(gè)對象,在內(nèi)存中是為其分配了空間的;
	數(shù)組名 a 在內(nèi)存空間中沒有分配到空間(這將導(dǎo)致&a操作的效果可能和預(yù)想的不大一樣)。
	可以理解為a指向一個(gè)含有5個(gè)整數(shù)的數(shù)組的指針,故 &a的類型為int(*)[5],不能用來初始化int */	

整理:

指針 類型
a int *
&a int (*) [5]

二維數(shù)組

int ia[3][4];
       int (*p)[4] = ia;      //ia 的類型就是 int(*)[4]
       int (*p)[3][4] = &ia;  //&ia的類型就是 int(*)[3][4]

整理:

指針 類型iaint (*) [4]&1aint (*) [3] [4]

2.2 理解復(fù)雜的數(shù)組的聲明

上述提到數(shù)組名是指向一個(gè)數(shù)組的指針,因此解釋一下一些復(fù)雜的數(shù)組聲明。加深理解

 int * ptr[10];             //ptr是含有10個(gè)  整形指針  的數(shù)組
   int & ref[10]  = /* ? */   //錯(cuò)誤,不存在引用的數(shù)組
   int (*parray) [5] = &a;   //parray指向一個(gè)含有5個(gè)整數(shù)的數(shù)組
   /*
   同時(shí)也是上述數(shù)組名的解釋
   *parray意味著parray是一個(gè)指針;
   右邊是[5]表明是指向大小為10的數(shù)組;
   左邊int表明數(shù)組中元素為int.
   */
   
   int (&array)[5] = a;      //array引用一個(gè)含有5個(gè)整數(shù)的數(shù)組

   int * (&array) [10]  = ptrs;
   //array是數(shù)組的引用, 該數(shù)組是含有10個(gè)指針的數(shù)組

2.3 數(shù)組名a、數(shù)組名取地址&a、數(shù)組首元素地址&a[0]、指向數(shù)組首元素的指針*p

int main()
{
	int a[] = { 0,1,2,3,4 };
	printf("%x\n", a);
	printf("%x\n", &a);
	printf("%x\n", &a[0]);

	int *p = &a[0];
	
	decltype(a) t;
	decltype(&a) tt;

	cout << p << endl;
	printf("%x,%x\n", a + 1, p + 1);
	printf("%x\n", &a + 1);

	cout << sizeof(a) << " " << sizeof(&a) << endl;
}

輸出

在這里插入圖片描述

  • a既然是種特殊的指針,那么其打印時(shí)就會(huì)是存的地址。
  • &a的類型是int(*)[5](讀法從小括號(hào)里往外,首先是指針,然后是大小為5的數(shù)組,然后數(shù)組元素類型是int),從局部變量中看到其類型也可寫成int[5] *:即指向大小為5的int數(shù)組的指針。由于數(shù)組名沒有內(nèi)存分配空間
  • &a[0]就是取一個(gè)int對象的地址,這個(gè)int對象是數(shù)組首元素。綜上所述,就造成了a &a &a[0]三者打印出來的地址是一樣的。
  • p,指向數(shù)組首元素的指針。
  • a + 1,p + 1都是按照元素大小的字節(jié)數(shù)(4字節(jié)),增加4。
  • &a + 1,前面說了 &a的類型是指向大小為5的int數(shù)組的指針,大小為5的int數(shù)組所占字節(jié)數(shù)為20,所以&a + 1就應(yīng)該增加20。
  • sizeof(a)為20,因?yàn)閿?shù)組總的字節(jié)大小為20。
  • sizeof(&a)為4,因?yàn)?code>&a是一種指針,指針在32位系統(tǒng)中占4字節(jié)。

2.4 對數(shù)組名以及取值符&的理解

數(shù)組中每個(gè)元素都是對象,即占有特定類型的內(nèi)存空間。(對象,占有一塊數(shù)組類型的內(nèi)存空間。因?yàn)閷ο笫侵敢粔K能存儲(chǔ)數(shù)據(jù)并且具有某種類型的內(nèi)存空間。)

數(shù)組名可以轉(zhuǎn)化為這個(gè)數(shù)組對象的首個(gè)元素的地址。

這里我們不去討論一維數(shù)組,直接從二維說起。所謂二維數(shù)組也是數(shù)組,只不過它的元素也是一個(gè)數(shù)組。

首先我們寫一個(gè)二維數(shù)組留作使用

#include<iostream>
using namespace std;
int a[][10]={
    {1,2,3,4,5,5,6,7,8,8},
    {10,12,32,42,51,15,16,71,121,18}
};

簡單說明一下數(shù)組:數(shù)組a 是包含2個(gè)元素的數(shù)組,每個(gè)元素是一個(gè)包含10個(gè) int 的數(shù)組。
既然說到數(shù)組名是其首個(gè)對象的地址那么來驗(yàn)證一下,測試數(shù)組名,以及對數(shù)組名求地址:

void test01(){
    cout << (long long)a << endl;         // 140273290059808
    cout << (long long)(a+1) << endl;     // 140273290059848
    // 相差40個(gè)字節(jié)
   }

(用long long 型一眼就能看出是40個(gè)字節(jié))

aa + 1 正好相差40個(gè)字節(jié),說明:

(1)數(shù)組名a 是(首元素{1,2,3,4,5,5,6,7,8,8})這一整行對象的地址,即首元素地址;

(2)所以在a+1偏移了一個(gè)元素大小——40字節(jié)。

void test01(){
    cout << (long long)&a << endl;        // 140273290059808
    cout << (long long)(&a+1) << endl;    // 140273290059888
    // 相差80個(gè)字節(jié)
   }

&a&a + 1 正好相差80個(gè)字節(jié),說明:

(1)取址符取得是整個(gè)對象的地址,&a 是對二維數(shù)組求址,針對的是整個(gè)對象;

(2) &a+1 偏移一位就變成了整個(gè)二維數(shù)組的尾地址,c++中的尾地址是對象所在地址的下一位。&a+1 正好比 a 多了 80 個(gè)字節(jié)。

在上面也提到數(shù)組名會(huì)自動(dòng)轉(zhuǎn)換成一個(gè)特殊指針(兩個(gè)表格當(dāng)中的總結(jié)),接下來將理解這個(gè)指針到底是什么?

從指針解引用方面理解:

void test03(){
    cout << *a << endl;     // 0x7f051ce02020
    //為了驗(yàn)證,我們偏移一下
    cout << *(a + 1) << endl; // 0x7f051ce02048
    // 正好相差40個(gè)字節(jié)
}

*a 把數(shù)組名解引用之后是首元素(因?yàn)閿?shù)組名是指向首元素的特殊指針),而首元素也是一個(gè)有10個(gè)元素的數(shù)組,現(xiàn)在 *a 是代表這個(gè)對象,輸出它就是此數(shù)組的首元素——1 的地址.。

cout << *(*a) << endl; //1    **a 即可	

第二層解掉:*(*a) 自然就是第一個(gè) int 型的元素。

cout << *a[0] << endl; //   1

因?yàn)橹羔樦赶驍?shù)組對象時(shí),可以用下標(biāo)訪問下一個(gè)位置,又 a 是指針指向了數(shù)組,下一個(gè)偏移為 0,即 * a = * (a + 0)

// cout << (a[0])[0] << endl; 
 cout << a[0][0] << endl;//   1

基于上述, *a 也就是a[0],也會(huì)自動(dòng)轉(zhuǎn)化為指向自己的首個(gè)對象(10個(gè)元素的第一個(gè)元素的位置)的指針。所以 a[0] 可以用下標(biāo)訪問數(shù)組對象(10個(gè)元素)內(nèi)其他元素:a[0][0] == 1

我們多搞幾個(gè)案例:

 // 要是訪問當(dāng)前行的下一個(gè)元素呢?將這個(gè)首地址
    cout << *(*a + 1) << endl;// 2 即 *((*a) + 1) 
    // 請注意這里的指針是 (*a),
    cout << (*a)[1] << endl; //    2
    // 同理(*a)相當(dāng)于*(a + 0) 即a[0] 
    cout << a[0][1] << endl; //2
    
    // 如果訪問下一行呢?
    cout << **(a+1) << endl;
    cout << *a[1] << endl; 
    cout << a[1][0] << endl; // *(a[1] + 0)
    
    // 第二行第二個(gè)元素呢?
    cout << *(*(a+1) +1 ) << endl;
    cout << *(a[1] +1) << endl;
    cout << a[1][1] << endl;

查看數(shù)組名類型理解

cout << typeid(*a).name()<< endl;  // A10_i
cout << typeid(&a[0]).name()<< endl; // PA10_i

A10_i :是由10個(gè) int 組成數(shù)組
PA10_i :是一個(gè)指針類型, 指向一個(gè)數(shù)組對象,這個(gè)數(shù)組對象有10個(gè)int型的對象。編譯器會(huì)識(shí)別為int(*)[10]

cout << typeid(a).name()<< endl; // A2_A10_i
cout << typeid(&a).name()<< endl; // PA2_A10_i	

A2_A10_i:由多維數(shù)組是數(shù)組的數(shù)組。A表示這個(gè)是數(shù)組類型2表示是兩個(gè)對象組成的數(shù)組,每個(gè)對象(A10_i)是由有10個(gè)對象的數(shù)組,這10個(gè)對象是int型的。

PA2_A10_i:是一個(gè)指針類型, 指向一個(gè)數(shù)組對象這個(gè)數(shù)組對象有2個(gè)數(shù)組型的對象。編譯器會(huì)識(shí)別為int(*)[2][10]

三、字符數(shù)組數(shù)組名

c++對待字符數(shù)組名不會(huì)輸出其地址,會(huì)直接輸出字符

#include <iostream>
using namespace std;
 
int main()
{
	//int a[5]={1,2,34,4,5};   //如果不是char型,cout<<"a="<<a<<endl;
	// 輸出的為int數(shù)組首地址。不會(huì)輸出數(shù)組中的值。
	char a[5]="aaaa";         //cout重載了char[],可以輸出整個(gè)字符串?dāng)?shù)組
	cout<<"a="<<a<<endl;
	return 0;
}

詳細(xì)參考這篇博客

到此這篇關(guān)于詳解C++數(shù)組和數(shù)組名問題(指針、解引用)的文章就介紹到這了,更多相關(guān)C++數(shù)組和數(shù)組名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中前綴和數(shù)組(算法)基本介紹

    C++中前綴和數(shù)組(算法)基本介紹

    前綴和(Prefix Sum)是指數(shù)組中某個(gè)位置之前的所有元素的和,本文將介紹C++中前綴和數(shù)組(算法)基本概念,感興趣的朋友一起看看吧
    2024-12-12
  • c++中的static修飾符示例詳解

    c++中的static修飾符示例詳解

    在c++中,靜態(tài)成員是屬于整個(gè)類而不是某個(gè)對象,靜態(tài)成員變量只存儲(chǔ)一份供所有對象共用,下面這篇文章主要給大家介紹了關(guān)于c++中static修飾符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10
  • C++鏈表節(jié)點(diǎn)的添加和刪除介紹

    C++鏈表節(jié)點(diǎn)的添加和刪除介紹

    大家好,本篇文章主要講的是C++鏈表節(jié)點(diǎn)的添加和刪除介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • C++超詳細(xì)講解auto與nullptr的使用

    C++超詳細(xì)講解auto與nullptr的使用

    C++11提供了nullptr用來取代0或者NULL。在C++11之前,使用NULL為空指針賦初值,但NULL其實(shí)就是0,這時(shí)會(huì)把NULL當(dāng)成0來用;在C++11中,我們在聲明一個(gè)變量或?qū)ο螅付ㄋ念愋蜁r(shí),可以不使用變量本身的類型而使用auto替代
    2022-05-05
  • 用C語言實(shí)現(xiàn)通訊錄

    用C語言實(shí)現(xiàn)通訊錄

    這篇文章主要為大家詳細(xì)介紹了用C語言實(shí)現(xiàn)通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 深入解析C++編程中的靜態(tài)成員函數(shù)

    深入解析C++編程中的靜態(tài)成員函數(shù)

    這篇文章主要介紹了深入解析C++編程中的靜態(tài)成員函數(shù),是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C/C++ break和continue區(qū)別及使用方法

    C/C++ break和continue區(qū)別及使用方法

    這篇文章主要介紹了C/C++ break和continue區(qū)別及使用方法的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • C++未定義行為(undefined behavior)

    C++未定義行為(undefined behavior)

    對于未定義行為,C++標(biāo)準(zhǔn)沒有明確規(guī)定編譯器們應(yīng)該怎么做,那么執(zhí)行的結(jié)果就是不可預(yù)料的。下面我們來詳細(xì)探討下
    2017-02-02
  • C++堆排序算法實(shí)例詳解

    C++堆排序算法實(shí)例詳解

    這篇文章主要介紹了C++堆排序算法,簡單分析了堆排序算法的原理并結(jié)合實(shí)例形式分析了C++實(shí)現(xiàn)堆排序的具體操作技巧,需要的朋友可以參考下
    2017-08-08
  • C++實(shí)現(xiàn)商店倉庫管理系統(tǒng)

    C++實(shí)現(xiàn)商店倉庫管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)商店倉庫管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

象山县| 玉龙| 瑞金市| 舟山市| 碌曲县| 东丰县| 江源县| 秦皇岛市| 咸丰县| 柘荣县| 新泰市| 邵阳市| 四会市| 金川县| 万山特区| 景东| 梁河县| 炉霍县| 贵溪市| 江华| 花莲县| 宁远县| 博白县| 宁波市| 丰原市| 丁青县| 三明市| 建昌县| 惠水县| 威海市| 景泰县| 武穴市| 丰台区| 澄城县| 佳木斯市| 卓尼县| 思南县| 永吉县| 南充市| 新营市| 福清市|