还在被C/C++指针折腾到抓狂吗?
很正常,我也是。
int num=1;
int* pnum=#
仅知道pnum类型是整型指针,以及怎样获取一个变量的指针的你,还是个指针小白,连指针的门槛大概都还没有迈进,前行的路上等待你的可还有指针2级,指针4级,指针6级,专业指针8级……
深知指针疼痛的博主,还在艰辛地奋斗在指针从入门到放弃的路上呢
嗯,程序中的天使和魔鬼,说的大概就是指针了。
来道指针4级题目看看:
想想下面的程序会怎样
#include "pch.h"
#include <iostream>
int addarr(const int* p1, int num)
{
std::cout << "p1:" << p1 << std::endl;
p1[0] = 2;
int theSum = 0;
//修改p1的值
p1 = new int[3];
std::cout << "修改后的p1:" << p1 << std::endl;
p1[0] = 2;
p1[1] = 4;
p1[2] = 6;
for (int i = 0; i < num; i++)
{
theSum += p1[i];
}
delete[] p1;
return theSum;
}
int main()
{
int arr[3] = { 1,2,3 };
std::cout << "arr:" << arr << std::endl;
int SumofArr = 0;
SumofArr = addarr(arr, 3);
std::cout << "SumofArr:" << SumofArr << std::endl;
}
事实上,这里面有一些不正确,无法编译的地方,见下面详细解释
#include "pch.h"
#include <iostream>
int addarr(const int* p1, int num)//p1是指向常量整数的指针(指针的指向可以更改,但是所指向的地址中存储的值不可以更改>_<)
{
std::cout << "p1:" << p1 << std::endl;//比如p1的值为 00CFFBE4
//p1[0] = 2; //(编译失败)试图改变所指向的常量整数是做不到的,即试图更改地址号00CFFBE4中存储的值是做不到的
int theSum = 0;
//修改p1的值,修改p1的指向
p1 = new int[3];//但是这里是可以编译通过,也可以运行的,
std::cout << "修改后的p1:" << p1 << std::endl;//p1的值,比如为0096DBD0
//p1[0] = 2;//这里又会导致编译失败,因为想修改地址号0096DBD0中存储的值是做不到!!因为p1是指向常量整数的指针
//p1[1] = 4;
//p1[2] = 6;
//for (int i = 0; i < num; i++)
//{
// theSum += p1[i];
//}
delete[] p1;
return theSum;
}
int main()
{
int arr[3] = { 1,2,3 };
std::cout << "arr:" << arr << std::endl;
int SumofArr = 0;
SumofArr = addarr(arr, 3);
std::cout << "SumofArr:" << SumofArr << std::endl;
}
明白了吗?你真的明白了吗?还不明白?明白了?真的明白了?你以为你真的明白了?
再看一遍题目,想想它会怎么样:
#include "pch.h"
#include <iostream>
int addarr(int* const p1, int num)
{
std::cout << "p1:" << p1 << std::endl;
p1[0] = 2;
int theSum = 0;
//修改p1的值,修改p1的指向
p1 = new int[3];
std::cout << "修改后的p1:" << p1 << std::endl;
p1[0] = 2;
p1[1] = 4;
p1[2] = 6;
for (int i = 0; i < num; i++)
{
theSum += p1[i];
}
delete[] p1;
return theSum;
}
int main()
{
int arr[3] = { 1,2,3 };
std::cout << "arr:" << arr << std::endl;
int SumofArr = 0;
SumofArr = addarr(arr, 3);
std::cout << "SumofArr:" << SumofArr << std::endl;
}
怎么样,茫然了点没有,懵逼了点没有?
来看看具体的解释
#include "pch.h"
#include <iostream>
int addarr(int* const p1, int num)//p1是指向整数的常量指针(指针的指向不可以更改,但是所指向的地址中存储的值可以更改>_<)
//觉得上面的注释似曾相识是否?仔细一看,那是不一样的
{
std::cout << "p1:" << p1 << std::endl;//比如p1的值为 00CFFBE4
p1[0] = 2; //更改数组中的值
int theSum = 0;
//修改p1的值,修改p1的指向
//p1 = new int[3];//这里导致编译失败!!p1是常量指针,不可以更改指向,不可以更改p1中存储的地址号!!
//std::cout << "修改后的p1:" << p1 << std::endl;
p1[0] = 2;//可以更改指向的地址中存储的值
p1[1] = 4;
p1[2] = 6;
for (int i = 0; i < num; i++)
{
theSum += p1[i];
}
//delete[] p1;
return theSum;
}
int main()
{
int arr[3] = { 1,2,3 };
std::cout << "arr:" << arr << std::endl; //小小的问题,arr的输出和p1的输出一样吗?
int SumofArr = 0;
SumofArr = addarr(arr, 3);
std::cout << "SumofArr:" << SumofArr << std::endl;
}
arr的输出和p1的输出一样吗?
当然一样了!函数addarr调用时,实参arr复制传递给了p1,arr和p1的值能不一样么?
怎么样,现在清醒了点没有?
清醒了吧,那再来懵逼点:
指针与常量的关系分三类,
(1)指向常量对象的指针
(2)指向某个对象的常量指针
(3)指向常量对象的常量指针
第一种情况下,不能修改被指向的对象,但可以使指针指向其他的对象;
int value=5;
const int* pvalue=&value;
*pvalue=6;//编译不通过
pvalue=nullptr;//可以
第二种情况下,不能修改指针中存储的地址,但可以修改指针指向的对象
int value=5;
int* const pvalue=&value;
*pvalue=6;//可以
pvalue=nullptr;//编译不通过
第三种情况下,指针和被指向的对象都定义成常量,因此都不能修改
int value=5;
int* const pvalue=&value;
*pvalue=6;//编译不通过
pvalue=nullptr;//编译不通过
哈哈哈哈哈哈……CNM…… MNP结束!