1. 基本概念
1.1 定义与规定
指针相当于一个变量,但是它存放的是其它变量在内存中的地址。指针名指向了内存的首地址。同类型指针变量可以相互赋值,指针很灵活,它可以指向任意类型的数据。
着重理解:ptr是一个指针变量,则ptr存储的是一个地址,而*ptr表示存储在该地址的值,*ptr与常规变量等效。
声明指针变量时注意:对每个指针变量,都需要使用一个*。在使用中,当*和&同时出现时,从右往左,依次抵消。
野指针:任意数值赋值给指针变量没有意义,这样的指针变量就是野指针,野指针指向的区域是未知的。
空指针:在C++中,值为0的指针变量被称为空指针,空指针不会指向有效的数据。
1.2 代码实例
#include<iostream>
using namespace std;
int main() {
//指针变量的声明和初始化
int num = 50;
int* p = #
// int* p;
// p = #
cout << p << endl;
cout << &num << endl;
//对p使用解除引用运算符*
//*p==num=50
cout << *p << endl;
//修改*p的值也会修改num的值
*p = 100;
cout << *p << endl;
cout << num << endl;
//注意,在使用中,当*和&同时出现时,从右往左,依次抵消
//void*:1.可以保存任意类型的地址 2.主要作为函数的参数
//void*指针变量,不要解除引用操作,不然会报错,因为系统不知道指针变量所指向的类型,不知道具体要获取多少宽度
void* q;
int number = 20;
q = &number;
//cout << *q << endl;
//如果想要通过指针变量q获取number的值,须进行强制类型转换
int* q_num = (int*)q;
cout << *q_num << endl;
//const和指针
const int* p1 = # //const在*的左边,const修饰的是*,*p1只读的,p1可读可写
//*p1 = 20;
int data = 20;
p1 = &data;
cout << *p1 << endl;
int* const p2 = #; //const在*的右边,修饰的是p2, *p2可读可写,p2只读
*p2 = 200;
cout << *p2 << endl;
//p2 = &data;
const int* const p3 = # //const在*的左右两边,*p3只读,p3只读
//*p3 = 10;
//p3 = &data;
//二级指针(一个指针变量保存的是另外一个指针变量的地址值)
int m = 10;
int* k = &m;
//定义一个二级指针
int** g = &k;
cout << m << endl;
cout << k <<endl;
cout << g << endl;
cout << *k << endl;
cout << *g << endl;
cout << **g << endl;
return 0;
}
2. 指针与数组
#include <iostream>
using namespace std;
//指针与数组
int main()
{
//指针在数组中的操作
//创建一个数组
int arr[5] = { 10,20,30,40,50 };
int* p = arr; //int* p; p=arr; 数组元素首地址给了p
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
cout << arr[i] << endl;
cout << p[i] << endl;
cout << *(arr + i) << endl;
cout << *(p + i) << endl; //上述输出全部等价
}
cout << sizeof(arr) << endl; //20
cout << sizeof(p) << endl; //4
int* p1 = &arr[2]; //p1指向数组元素为30的地址
cout << "p1[1]=" << p1[1] << endl; //40
cout << "p1[-1]=" << p1[-1] << endl; //20
int* p2 = arr;
cout << *p2++ << endl; //10 ,先获取p2指向的元素10,p2最后指向第二个元素
cout << (*p2)++ << endl; //20 ,先获取p2指向的元素20,(*p2)+1=21
cout << *(p2++) << endl; //21 ,获取p2指向的元素21
//指针数组:本质是数组,数组中的每个元素都是指针类型
int num1 = 10;
int num2 = 20;
int num3 = 30;
int num4 = 40;
//定义一个数组,保存四个变量的地址
int* arry[4] = { &num1,&num2,&num3,&num4 };
//对数组中的元素进行操作
*arry[2] = 300;
cout << *arry[2] << endl;
cout << sizeof(arry) << endl; //32位输出16,64位输出32
cout << sizeof(arry[0]) << endl;//32位输出4,64位输出8
//对指针数组进行遍历
for (int i = 0; i < sizeof(arry) / sizeof(arry[0]); i++)
{
cout << arry[i] << "-----" << *arry[i] << endl;
}
return 0;
}
3. 指针与字符
#include <iostream>
using namespace std;
//指针和字符串
int main()
{
//创建一个字符串
char flower[10] = "rose";//字符串常量代表字符串,返回的值是首个元素的地址
cout << flower << "s are red" << endl; //roses are red
//数组名flower 时首元素的地址,当cout对象在处理字符地址的时候,不是打印地址,而是打印地址对应字符的内容,
//把它当成字符串处理,也就是继续往后输出后面的字符,直到遇到空字符'\0'
int arr[] = { 1,2,3 };
cout << arr << endl; //0116F92C, 首地址
//指针类型
char ch = 'A';
char* p_ch = &ch;
cout << p_ch << endl; //A烫烫烫烫
//在cout中,char数组名、char指针以及引号括起来的字符串常量都被解释为字符串第一个字符的地址
const char* p_flower = "rose";
cout << p_flower << endl;//rose
//字符串指针变量与字符串的区别
//字符串指针变量
const char* str1 = "hello world";//没有const会报错,字符保存在文字常量区
cout << sizeof(str1) << endl; //4
cout << *str1 << endl; //h
cout << *(str1 + 1) << endl; //e
//*str1='H'; //错误的,文字常量区只读
// str1变量,在栈区开辟空间,“hello world”在文字常量区开辟空间,str1保存首元素地址,不能对字符串内容修改
// str1本质是变量,可以++
str1++;
//字符串
char str2[] = "hello world";
cout << str2 << endl;//hello world
cout << sizeof(str2) << endl;//12
*str2 = 'H';
cout << str2 << endl;//Hello world
//str2跟据初始化字符串的大小开辟空间,并且直接存储该字符串的内容,可以通过str2对字符串进行写操作
//str2是数组名,是一个符号常量,不能++
//str2++;
char* p = str2;
p++;
//字符指针数组
const char* arr1[4] = { "hahaha","hehehe","xixixi","huhuhu" };
cout << sizeof(arr1) << endl;//16
//遍历数组
for (int i = 0; i < sizeof(arr1) / sizeof(arr1[1]); i++)
{
cout << arr1[i] << endl;
}
cout << *(arr1[1] + 1) << endl;//e
cout << arr1[1][1] << endl;//e 两者等价
return 0;
}