一. 指針
1. 指針的基本概念
指針的作用: 可以通過(guò)指針間接訪(fǎng)問(wèn)內(nèi)存
- 內(nèi)存編號(hào)是從0開(kāi)始記錄的氛谜,一般用十六進(jìn)制數(shù)字表示
- 可以利用指針變量保存地址
2. 指針變量的定義和使用
-
定義指針 :
數(shù)據(jù)類(lèi)型 * 指針名;
-
變量的地址 :
&變量名
-
指針指向變量的地址 :
指針 = &變量;
-
通過(guò)指針取值 :
*指針
-
在遍歷中移動(dòng)指針:
指針++
-
用指針訪(fǎng)問(wèn)結(jié)構(gòu)體的數(shù)據(jù):
指針->屬性
using namespace std;
int main() {
int a = 10; //定義整型變量a
//指針定義語(yǔ)法: 數(shù)據(jù)類(lèi)型 * 變量名 ;
int * p;
//指針變量賦值
p = &a; //指針指向變量a的地址
cout << &a << endl; //打印數(shù)據(jù)a的地址
cout << p << endl; //打印指針變量p
//2托慨、指針的使用
//通過(guò)*操作指針變量指向的內(nèi)存
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
指針變量和普通變量的區(qū)別
- 普通變量存放的是數(shù)據(jù), 指針變量存放的是地址
- 指針變量可以通過(guò)" * "操作符丛晦,操作指針變量指向的內(nèi)存空間,這個(gè)過(guò)程稱(chēng)為解引用
3 指針?biāo)純?nèi)存空間
所有指針類(lèi)型在32位操作系統(tǒng)下是4個(gè)字節(jié)
所有指針類(lèi)型在64位操作系統(tǒng)下是8個(gè)字節(jié)
4. 空指針
空指針:指針變量指向內(nèi)存中編號(hào)為0的空間, 注意:空指針指向的內(nèi)存是不可以訪(fǎng)問(wèn)的
#include <iostream>
using namespace std;
int main() {
//指針變量p指向內(nèi)存地址編號(hào)為0的空間
int * p = NULL;
//訪(fǎng)問(wèn)空指針報(bào)錯(cuò)
//內(nèi)存編號(hào)0 ~255為系統(tǒng)占用內(nèi)存,不允許用戶(hù)訪(fǎng)問(wèn)
cout << "*p at"<< *p << endl;
system("pause");
return 0;
}
5. 野指針
野指針:指針變量指向非法的內(nèi)存空間
總結(jié):空指針和野指針都不是我們申請(qǐng)的空間,因此不要訪(fǎng)問(wèn)。
6. const 常量指針
常量指針 , 這個(gè)指針只能指向常量, 指向的值被視為是常量
const修飾的是指針企蹭,指針指向可以改,指針指向的值不可以更改
int a = 10;
int b = 10;
//const修飾的是指針智末,指針指向可以改谅摄,指針指向的值不可以更改
const int * p1 = &a;
p1 = &b; //正確
//*p1 = 100; 報(bào)錯(cuò)
7. const 恒定向指針(指針常量)
const 恒定向指針,使得指針只能恒定指向某個(gè)地址
指針指向不可以改系馆,指針指向的值可以更改
int * const p2 = &a;
//p2 = &b; //錯(cuò)誤
*p2 = 100; //正確
8. const 常量恒定向指針
無(wú)用
//const既修飾指針又修飾常量
const int * const p3 = &a;
9. 指針指向數(shù)組
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int * p = arr; //指向數(shù)組的指針
cout << "第一個(gè)元素: " << arr[0] << endl;
cout << "指針訪(fǎng)問(wèn)第一個(gè)元素: " << *p << endl;
for (int i = 0; i < 10; i++)
{
//利用指針遍歷數(shù)組
cout << *p << endl;
p++;
}
p -= 10; // 必須復(fù)位才行
system("pause");
return 0;
}
注意 : 這樣取值會(huì)移動(dòng)指針位置, 記得復(fù)位, 否則下次再讀就錯(cuò)了
10. 指針遍歷數(shù)組的兩種方法:
(1). 移動(dòng)指針遍歷
如上面的程序, 這種遍歷方法會(huì)移動(dòng)指針, 如果想再次遍歷, 記得移回來(lái)! 否則就指錯(cuò)位置了
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int *p = arr; //指向數(shù)組的指針
for (int i = 0; i < 10; i++)
{
//利用指針遍歷數(shù)組
*p = i;
p++;
}
p -= 10; // 由于指針移動(dòng)了, 下次遍歷前要移回來(lái)
for (int i = 0; i < 10; i++)
{
//利用指針遍歷數(shù)組
cout << *p << endl;
p++;
}
return 0;
p -= 10; // 由于指針移動(dòng)了, 下次遍歷前要移回來(lái)
for (int i = 0; i < 10; i++)
{
//利用指針遍歷數(shù)組
cout << *p << endl;
p++;
}
return 0;
}
(2). 使用 p[索引]取值法
賦值時(shí), 可以用 p[索引] = 值 進(jìn)行賦值, 也能用 p[索引] 取值, 因?yàn)闆](méi)有移動(dòng)指針, 可以隨便取值
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int *p = arr;
// 賦值時(shí), 可以用 p[索引] = 值
for (int i = 0; i < 10; i++)
{
p[i] = i;
}
// 能用 p[索引] 取值
for (int i = 0; i < 10; i++)
{
cout << "????" << p[i] << endl;
}
// 因?yàn)闆](méi)有移動(dòng)指針, 再取也沒(méi)事
for (int i = 0; i < 10; i++)
{
cout << "????" << p[i] << endl;
}
return 0;
}
11. 指針和函數(shù)傳參
如果不想修改實(shí)參送漠,就用值傳遞,如果想修改實(shí)參由蘑,就用地址傳遞
#include <iostream>
using namespace std;
//值傳遞
void swap1(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
//地址傳遞
void swap2(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int a = 10;
int b = 20;
swap1(a, b); // 值傳遞不會(huì)改變實(shí)參
cout << "a = " << a << endl;
cout << "b = " << b << endl;
swap2(&a, &b); //地址傳遞會(huì)改變實(shí)參
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
二. 結(jié)構(gòu)體
結(jié)構(gòu)體可以理解為用戶(hù)創(chuàng)建的一個(gè)數(shù)據(jù)類(lèi)型
1. 創(chuàng)建結(jié)構(gòu)體
語(yǔ)法:struct 結(jié)構(gòu)體名 { 結(jié)構(gòu)體成員列表 }闽寡;
通過(guò)結(jié)構(gòu)體創(chuàng)建變量的方式有三種:
- struct 結(jié)構(gòu)體名 變量名
- struct 結(jié)構(gòu)體名 變量名 = { 成員1值 , 成員2值...}
- 定義結(jié)構(gòu)體時(shí)順便創(chuàng)建變量(實(shí)例)
//結(jié)構(gòu)體變量創(chuàng)建方式3 創(chuàng)建結(jié)構(gòu)體student的同時(shí), 創(chuàng)建 student類(lèi)型變量 stu3
struct student
{
//成員列表
string name; //姓名
int age; //年齡
int score; //分?jǐn)?shù)
}stu3;
2. 實(shí)例化結(jié)構(gòu)體
方法一:
//結(jié)構(gòu)體變量創(chuàng)建方式1
int main()
{
struct student stu1; // struct 關(guān)鍵字可以省略
// 變量賦值
stu1.name = "anny";
stu1.age = 8;
stu1.score = 100;
// 輸出
cout << "name:" << stu1.name << ", age:" << stu1.age << ", score:" << stu1.score << endl;
system("pause");
return 0;
}
方法二:
int main()
{
student stu1 = {"anny",8,100}; // struct 關(guān)鍵字可以省略
// 輸出
cout << "name:" << stu1.name << ", age:" << stu1.age << ", score:" << stu1.score << endl;
system("pause");
return 0;
}
方法三:
創(chuàng)建結(jié)構(gòu)體時(shí)就實(shí)例化
實(shí)例化時(shí), struct關(guān)鍵字可以省略, 我還是省略了吧, 直接按面向?qū)ο笕ダ斫?/p>
3. 結(jié)構(gòu)體數(shù)組
// struct 結(jié)構(gòu)體名 數(shù)組名[元素個(gè)數(shù)] = { {} , {} , ... {} }
// 結(jié)構(gòu)體名 數(shù)組名[元素個(gè)數(shù)] = { {} , {} , ... {} }
#include <iostream>
using namespace std;
//結(jié)構(gòu)體定義
struct student
{
//成員列表
string name; //姓名
int age; //年齡
int score; //分?jǐn)?shù)
};
int main()
{
//結(jié)構(gòu)體數(shù)組
student stu_arr[3] =
{
{"anny", 18, 80},
{"haha", 19, 60},
{"gaga", 20, 70}};
// 輸出
for (int i = 0; i < 3; i++)
{
cout << "name: " << stu_arr[i].name << " age: " << stu_arr[i].age << " score: " << stu_arr[i].score << endl;
}
system("pause");
return 0;
}
實(shí)例化時(shí), struct關(guān)鍵字還是可以省略
4. 指針指向結(jié)構(gòu)體
利用操作符 ->
可以通過(guò)結(jié)構(gòu)體指針訪(fǎng)問(wèn)結(jié)構(gòu)體屬性
#include <iostream>
using namespace std;
//結(jié)構(gòu)體定義
struct student
{
//成員列表
string name; //姓名
int age; //年齡
int score; //分?jǐn)?shù)
};
int main()
{
struct student stu = {
"anny",
18,
100,
};
struct student *p = &stu;
p->score = 80; //指針通過(guò) -> 操作符可以訪(fǎng)問(wèn)成員
cout << "name: " << p->name << " age: " << p->age << " score: " << p->score << endl;
system("pause");
return 0;
}