目录
指针和一维数组04例 关于数组、数组地址和数组项的地址的返回值
1.指针01例 指针的使用和意义
#include <iostream>
using namespace std;
int main( )
{
int *p; //定义了一个变量名为p的int* (读作int类型的指针)
//指针p指向一块int类型的内存地址,类似空快递盒上面单号。
//所以输出p是一个地址值 如:0x1
//那么*p输出什么?这个*叫做解引用运算符,与上文的int *里的*是两个不同的东西。
//*p是这个空的内存里面存着的int类型的具体值,类似单号为p的快递盒里面的具体物品。
//而我们没有让这个指针指向一块有具体值的内存地址,所以*p什么也无法输出。
//值得注意的是,这样的写法并不规范,这是一个野指针,调用*p会导致程序运行时异常。
//即使我们通过int* p=0或NULL 这也只是表示p是一个空指针,同样不建议调用*p。
int a=100;
p=&a; //指针p指向变量a的地址
//此时,p返回值就是a的地址值,如:0x6ffe44。
//而*p,读作解引用p,它的返回的值是p指向的内存地址里存放的int值,故*p==100。
a=1000; //p依然返回a的地址值,但*p顺着地址找过去的a变成了1000,所以*p==1000
*p=1; //直接修改指针p指向的内存地址里存储的int a,所以a==1,*p==1,p还是a的地址值。
cout<<"a:"<<a<<endl;//1
cout<<"*p:"<<*p<<endl;//1
return 0;
}
指针02例 野指针
#include <iostream>
using namespace std;
int main()
{
int a;
int* p; //野指针 即在初始化时未指向一块合法内存空间的指针
cout<<p<<endl;
cout<<*p<<endl; //错误 解引用p必须保证指针合法
p=&a; //初始化一块合法内存
cout<<p<<endl;
cout<<*p<<endl; //正确
return 0;
}
指针03例 使用*p时(解引用指针)的注意事项
#include <iostream>
using namespace std;
int main( )//在使用*p(解引用p)之前 一定要确保指针p指向一块有效的内存地址
{
int a;
int* p;
int* q=new int; //指针q指向动态分配的一块int类型的地址
//new int返回的数据类型是地址值
p=&a; //指针p指向a的地址值
*q=a; //解引用q 为q指向的int内存地址的内存赋值为a
cout<<p<<endl; //a的地址值
cout<<*p<<endl; //a的值
cout<<q<<endl; //q指向的地址值
cout<<*q<<endl; //解引用q,也就是a的值
return 0;
}
2.指针和函数01例 传入参数为指针类时
#include <iostream>
using namespace std;
int oldAdd(int x){ //int函数oldAdd 传入参数为一个int类型的形参x
return ++x; //返回一个int类型的数字,值为x+1
} //我们如果在主函数中使用这个函数,需要写a=oldAdd(a);
//有没有更加简洁的写法呢?
void add(int* x){ //void函数add,传入参数为一个int类型的指针,形参为x
cout<<"x:"<<*x<<endl;
(*x)++; //这里*x需要加上括号 因为++运算符的优先级比解引用运算符*高
//我们在《指针和数组》中再讲*p++的意思和用法
//解引用x,返回结果自增1
cout<<"x:"<<*x<<endl;
}
int main( )//主函数
{
int a=100;
int *p=&a;
add(p);
cout<<"a:"<<a<<endl; //101
return 0;
}
指针和函数02例 返回参数为指针类时
#include<iostream>
using namespace std;
int* test(){
int a = 10; //局部变量存在栈区,由编译器在函数执行完后自动释放
return &a; //注意事项:不要直接返回局部变量的地址
//解决方法:在堆区开辟一块内存空间
//int *a=new int(10); //返回类型为地址型 即指针
//return a;
}
int main(){
int *ref=test();
cout<<*ref<<endl; //10 这里临时保存了一次
//但第二次就会释放这块内存空间 *ref就成了野指针
cout<<*ref<<endl; //0 dev5.11版本的结果,vs可能会是别的值,但都是非法的内存空间
}
3.指针和一维数组01例 指针的前后移动
#include <iostream>
using namespace std;
void add(int* x){
cout<<"x:"<<*x<<endl; // 输出解引用x的值
cout<<*x++<<endl; // 1.x++返回x,2.解引用x,语句结束后x+1,指针x以int为单位后移一位。
// 因为数组存储在一串连续的内存地址上
// 所以指针的加/减n就是向后/前移动n个单位地址
cout<<"x:"<<*x<<endl; // 指针x移动后,解引用看看
}
int main()
{
int a[]={10, 20, 30};
int* p=a; //p指向a[0],也可以写成int* p=a+0,a默认返回a[0]的地址值
int* q=&a[0]; //q指向a[0],和上面的p是一样的指向,这里是指向一维数组的两种写法
add(p);
add(q);
return 0;
}
指针和一维数组02例 定义指针类型的一维数组 (指针数组)
#include <iostream>
using namespace std;
int main()
{
int* p[3]; //定义了int* 类型的数组p
//数组p[3]是指针,指向int类型的内存空间
int a[]={1,2,3};
for(int i=0;i<3;i++){
p[i]=&a[i]; //数组p的每一个p[i]都是一个int类型的指针 即int* 类型
cout<<*p[i]<<endl;
}
return 0;
}
指针和一维数组03例 数组名的类型和数组名的地址的类型
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
int a[]={1,2,3};
int b[3][3]={{1,2,3},{4,5,6},{7,8,9}};
cout<<typeid(a).name()<<endl; //A3_i //a是长度为3的int数组类型,A是array(数组)
cout<<typeid(&a).name()<<endl; //PA3_i //&a是指针类型,指向长度为3的int数组
//P是ptr(指针)
cout<<typeid(a[0]).name()<<endl; //i //a[0]是int类型,i是int
cout<<typeid(b).name()<<endl; //A4_A3_i //b是4个长度为3的int数组的二维数组类型
cout<<typeid(&b).name()<<endl; //PA4_A3_i //&b是指针类型,
//指向4个长度为3的int数组的二维数组
cout<<typeid(b[0]).name()<<endl; //A3_i //b[0]是长度为3的int数组类型
return 0;
}
指针和一维数组04例 关于数组、数组地址和数组项的地址的返回值
#include <iostream>
using namespace std;
int main()
{
int a[]={1,2,3};
cout<<a<<endl;
cout<<&a<<endl;
cout<<&a[0];
//这三个输出结果都是一样的地址值,为什么?
//上个例子我们知道了a,&a和a[0]的类型
//a[0]的返回值就是1,这个我们很好理解
//a的返回值呢?它是数组类型,我们该返回什么?C++在这里做了隐式转换
//a的返回值转换为了int* 类型,也就是指向一个int类型的指针,它指向数组的第一个数a[0]
//所以直接输出a,相当于输出了&a[0],也就是a[0]的地址值
//并且它的运算是以int为单位左右移动,所以a+1指向的是下一个数组元素
//&a的返回值呢?它是PA3_i类型,是指向长度为3的int数组的指针 类型
//所以&a返回的是数组a的地址值,这里只返回a的起始地址,即a[0]的地址值
//所以尽管它们三个输出结果是一样的,但它们的数据类型不一样
//那么又来了一个问题
//我们之前定义过 int* p[3],它的类型是A3_Pi,什么意思呢?可以先看A3_P,再看Pi
//意思是数组p[3]为指针类型,指向一个int类型的内存空间
//也就是数组中的三个元素都是指针类型,都是int*类型
//还记得PA3_3i类型吗?
//就是上文中&a的类型。是PA3_i类型,是指向长度为3的int数组的指针,P指向A3_i
//它们两个之间区别就出来了。
return 0;
}
指针和一维数组05例 指向指定长度数组的指针(数组指针)
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
int a[]={1,2,3};
int(* p)[3]; //p是指针,指向int[3]类型的内存空间
p=&a;
cout<<typeid(p).name()<<endl; //PA3_i
cout<<typeid(*p).name()<<endl; //A3_i
//这样,p指向了一块长度为3的int类型数组
//解引用p 得到数组a,用访问数组中元素的方式即可获取元素的值
cout << (*p)[0] << endl; // 输出 1
cout << (*p)[1] << endl; // 输出 2
cout << (*p)[2] << endl; // 输出 3
return 0;
}
指针和一维数组06例 数组指针作为函数的传入参数
#include <iostream>
#include <typeinfo>
using namespace std;
void arr3Add1(int(* x)[3]){//x是指针,指向int[3]类型的内存空间
(*x)[0]++;
(*x)[1]++;
(*x)[2]++;
}
int main()
{
int a[]={1,2,3};
int(* p)[3];
p=&a;
cout<<typeid(p).name()<<endl; //PA3_i
cout<<typeid(*p).name()<<endl; //A3_i
arr3Add1(p);
cout << (*p)[0] << endl; // 输出 2
cout << (*p)[1] << endl; // 输出 3
cout << (*p)[2] << endl; // 输出 4
return 0;
}
4.常量指针和指针常量例01 基本功能和区别
#include<iostream>
using namespace std;
int main(){
int a = 10;
int b = 20;
const int* ptr1 = &a; // 常量指针指向的值不可修改,但指针本身可以修改。
*ptr1 = 30; // 错误:指向的值不可修改
ptr1 = &b; // 正确:指针本身可以修改
int c = 10;
int d = 20;
int* const ptr2 = &c; // 指针常量的值(即指针指向的地址)不可修改,但指向的值可以修改。
*ptr2 = 30; // 正确:指向的值可以修改
ptr2 = &d; // 错误:指针本身不可修改
return 0;
//关于区分的一些理解
//const int * ptr1其实也能写成int const * ptr1
//表示ptr指针指向一个const int类型的值 那么这个值被const 修饰,自然就不能变
// 这个可以和int*ptr一起理解 指针指向一个int类型的值
//int* const ptr2 表示一个ptr是一个常量且是指针,那么指针的值是地址,地址自然就不能变
}
5.指针指向一个类时 例01
#include<iostream>
using namespace std;
//一个person类
class Person{
public:
string name;
int age;
Person(string name,int age){
this->name=name;//this 是一个指向当前对象的指针,而不是对象本身。
this->age=age;//如果一定要通过.访问的话可以使用(*this).name
//意思就是解引用指针,然后访问指向的对象的内部属性
}
};
int main(){
Person p("张三",18);
Person* ptr = &p;//定义一个指向person类的指针
cout<<p.name<<endl;
cout<<p.age<<endl;
cout<<ptr->name<<endl;//通过->箭头去访问指向的对象内部属性
cout<<ptr->age<<endl;
return 0;
}

2879

被折叠的 条评论
为什么被折叠?



