C++自学20:指针/指针的指针/const
原创
©著作权归作者所有:来自51CTO博客作者文天大人的原创作品,请联系作者获取转载授权,否则将追究法律责任
指针,32位系统一定占据4个字节,64位系统一定占8个字节
定义指针
int* a{};
std::cout<<a<<std::endl;
int *b{};
std::cout<<b<<std::endl;
上面定义了一个int类型的指针,a表示指针起始地址,因为int的大小是4,所以int*的意思是指针每次移动都移动4个字节
int a = 666;
//获取a的内存地址,是pa,C++中使用&符号来获取指定变量的内存地址
int* pa = &a;
//在pa前面加个星号,*pa叫做间接运算符,C++中使用间接运算符来修改内存的值
*pa = 777;
std::cout << a;
指针数组(注意不是数组指针)
int a[3]{11,22,33};
int * pa[3]{};
for (int i = 0; i < 3;i++) {
pa[i] = &a[i];
}
for (int* p:pa) {
std::cout << p << std::endl;
}
关于指针的移动
int a = 9999;
long long b = 9999;
// 挪动1次指针,指针走4个字节,因为int是4个字节
std::cout << &a << std::endl;
std::cout << &a+1 << std::endl;
// 挪动1次指针,指针走8个字节,因为longlong是8个字节
std::cout << &b << std::endl;
std::cout << &b+1 << std::endl;
先说指针类型转换,下面演示将一个int类型的指针转换成char类型的指针
int main()
{
int a = 1;
char *p = (char*)&a;
std::cout << &a <<"\n";
std::cout << p << "\n";
}
上面的代码第二次打印的时候会打印出乱码,
因为是个char是字符类型,所以cout把char类型的指针当做字符串来处理,打印的时候会以’\0’结束,但是指针是没有’\0’的,所以乱码,此时应该将上面的代码再次转换成void类型的指针,如下
int main()
{
int a = 1;
char *p = (char*)&a;
std::cout << &a <<"\n";
std::cout << (void*)p << "\n";
}
这样两次打印的地址就是相同的了
为指针区分不同的类型,意义在于从一个变量的首地址读取数据的时候,具体读多长。比如一个CPU可以根据该指针是int类型,那么一次就读取4个字节的长度,如果是char类型,就读取1个字节的长度
所以int类型的指针++一次,是加4个字节,而char类型指针++一次是1个字节
指针自增
int a = 666;
int* pa = &a;
std::cout << pa << std::endl;
// 注意这个写法,先打印pa所指向的值,然后指针再加1
std::cout << *pa++ << std::endl;
std::cout << pa << std::endl;
指针的指针,最后一个指针,叫做基址,就是下面代码的ppa,修改**ppa的时候,并不是修改pa,而是直接修改了它最终指的那个值
int a = 666;
int* pa = &a;
int** ppa = &pa;
**ppa=777;
std::cout << *pa << std::endl;//打印出777
常量的指针(const int*)
const int a = 666;
const int* pa = &a;
//*pa = 55;此处报错,不允许修改a的值
std::cout << *pa << std::endl;
//--------------------------
//所以我们定义一个int类型指针,而不是常量int指针,像下面这样
int* pb = (int*)&a;
*pb = 55;
std::cout << *pb << std::endl;
// 然后接下来我们继续输出a的值,很有意思,a的值并没有被改
std::cout << a << std::endl;//666
指针常量(注意不是常量的指针)
int a = 666;
int b = 0;
int* const pa = &a;
//pa = &b;此处报错,pa只能只想a所在的地址,不可以在指向其他位置,但是a的值可以改
std::cout << *pa << std::endl;
个人总结:关于星号与const的优先级,星号的优先级更高,星号修饰什么,就是什么的指针,比如星号修饰const int,那么这就是常量的指针,星号只修饰int,那么这是int类型的指针,知道该指针类型了,然后再看const就好记了
一维数组指针
int a[2] = { 11,12 };
int* pb = a;
//打印出12
std::cout << pb[1]<< std::endl;
多维数组指针
// 定义一个2行,3列的数组
int a[2][3] = {
{11,12,13},
{21,22,23}
};
//此处的3,就是列数,上面数组是几列,此处就要写几
int (*pa)[3]=a;
//因为这是数组指针,所以它有下面这种特性
std::cout << pa[0][2] << std::endl;//打印出13
//下面这行代码强转,也可以与一维数组一样,只不过这样没有了多维数组的指针特性,仅此而已
int* pb = (int*)a;
多维数组指针的挪动(注意不包括一维数组)
int a[2][3] = {
{11,12,13},
{21,22,23}
};
int(*pa)[3] = a;
std::cout << pa << std::endl;
//因为定义了每行三条数据
//所以此处比上一行多出12
std::cout << pa+1 << std::endl;