相信有很多刚开是学习C++的朋友都会遇到这样的情况,在编写C++代码时无论是变量的声明和定义,函数的声明和定义,判断语句,循环和分支控制都能够轻松上手,就算有感到困难的地方多努力一下也可以克服。直到遇到了C++的指针,就感觉前面的很多东西跟白学了一样,特别是代码当中混有指针的时候,只觉得脑子都被绕晕过去了。那么笔者在这里就要为很多新人朋友解决这个问题,因为笔者平时有其他的事情需要忙,还要准备编写代码准备案例,可能会分成几篇给大家讲完,所以请大家保持一些耐心。
1、指针的定义
市面上的很多文章或者是教材都会这样定义指针的:指针是一个变量,存储的数值是变量的地址。声明的方式是 type *ptr = nullptr;type必须是C++有效类型。
其实要是只是想要使用指针的话,知道上面这些定义也是足够了,但是笔者希望大家对指针能有更深一点的理解,遇到的一些疑惑才能迎刃而解。前面的定义当中提到指针存放的是地址,那么地址它又是什么类型的了?我们要存放整形数据的时候使用的是int,存放浮点型数据的时候使用的是float或者是double,存放布尔型数据的时候使用的是bool,存放地址的时候使用的类型只要是有效类型就可以了,这就让人感到费解了,难道不应该有一个专门的地址类型来存放吗?
2、指针的本质
其实大家不用太在意指针前面的这个类型,应为指针的本身跟前面的类型type是没有任何关系的,type *ptr = nullptr 这句话当中无论type到底是什么指针的实际类型是不会发生任何改变的,在同一个编译器下所有的指针的类型全部都相同,并且大小一致,因为所有的指针都是同一种整型数据。请看下面的案例
定义一个Book类型
#include<iostream>
#include<string>
#ifndef BOOK
#define BOOK
struct Book{
std::string mName;
int mID;
};
#endif // !BOOK
测试案例如下
int main() {
int var = 8;
float var1 = 8.0f;
double var2 = 8.0;
bool var3 = true;
Book book;
book.mID = 1;
book.mName = "C++入门到精通";
int* ptr = nullptr;
float* ptr1 = nullptr;
double* ptr2 = nullptr;
bool* ptr3 = nullptr;
Book* pBook = nullptr;
std::cout << "size of var: " << sizeof(var)<<std::endl;
std::cout << "size of var1: " << sizeof(var1)<<std::endl;
std::cout << "size of var2: " << sizeof(var2)<<std::endl;
std::cout << "size of var3: " << sizeof(var3)<<std::endl;
std::cout << "size of book: " << sizeof(book)<<std::endl;
std::cout << "\n";
std::cout << "size of ptr: " << sizeof(ptr) << std::endl;
std::cout << "size of ptr1: " << sizeof(ptr1) << std::endl;
std::cout << "size of ptr2: " << sizeof(ptr2) << std::endl;
std::cout << "size of ptr3: " << sizeof(ptr3) << std::endl;
std::cout << "size of pBook: " << sizeof(pBook) << std::endl;
return 0;
}
运行结果如下所示:
3、指针的赋值
如果真的就是前面说的那样,那么任意类型的指针应该可以任意指向某一个地址。是的这种理解没有任何的问题,请看下面的案例
int main() {
int var = 8;
float var1 = 8.0f;
double var2 = 8.0;
bool var3 = true;
Book book;
book.mID = 1;
book.mName = "C++入门到精通";
int* ptr = nullptr;
float* ptr1 = nullptr;
double* ptr2 = nullptr;
bool* ptr3 = nullptr;
Book* pBook = (Book*) & var;
std::cout << "size of var: " << sizeof(var)<<std::endl;
std::cout << "size of var1: " << sizeof(var1)<<std::endl;
std::cout << "size of var2: " << sizeof(var2)<<std::endl;
std::cout << "size of var3: " << sizeof(var3)<<std::endl;
std::cout << "size of book: " << sizeof(book)<<std::endl;
std::cout << "\n";
std::cout << "size of ptr: " << sizeof(ptr) << std::endl;
std::cout << "size of ptr1: " << sizeof(ptr1) << std::endl;
std::cout << "size of ptr2: " << sizeof(ptr2) << std::endl;
std::cout << "size of ptr3: " << sizeof(ptr3) << std::endl;
std::cout << "size of pBook: " << sizeof(pBook) << std::endl;
std::cin.get();
return 0;
}
这段代码可以成功编译并运行,然后我们可以通过地址到内存当中去找到对应的数据(打断点进入调试模式,选中调试->窗口->内存->内存1)
白色方框当中是地址,复制到内存1调试窗口当中,并按一下回车键。
这下我们就能看到8这个数据了,所以任意类型的指针应该可以任意指向某一个地址
4、类型的作用那又是什么了
其实定义指针的类型只是告诉系统,这个地址的数据到底应该怎样处理。比如说某个地址下存储的是float类型的数据,那么我们肯定要用float类型的指针了,这样才能保证数据被正常的处理。我们看一下下面的案例
int main() {
int var = 8;
float var1 = 8.0f;
double var2 = 8.0;
bool var3 = true;
Book book;
book.mID = 1;
book.mName = "C++入门到精通";
int* ptr = nullptr;
float* ptr1 = nullptr;
double* ptr2 = nullptr;
bool* ptr3 = nullptr;
Book* pBook = (Book*) & var;
std::cout << "size of var: " << sizeof(var)<<std::endl;
std::cout << "size of var1: " << sizeof(var1)<<std::endl;
std::cout << "size of var2: " << sizeof(var2)<<std::endl;
std::cout << "size of var3: " << sizeof(var3)<<std::endl;
std::cout << "size of book: " << sizeof(book)<<std::endl;
std::cout << "\n";
std::cout << "size of ptr: " << sizeof(ptr) << std::endl;
std::cout << "size of ptr1: " << sizeof(ptr1) << std::endl;
std::cout << "size of ptr2: " << sizeof(ptr2) << std::endl;
std::cout << "size of ptr3: " << sizeof(ptr3) << std::endl;
std::cout << "size of pBook: " << sizeof(pBook) << std::endl;
std::cout << "\n";
long number = 8L;
ptr = (int*) & var1;
std::cout << "ptr -> value is " << *ptr << std::endl;
ptr = (int*)&number;
std::cout << "ptr -> value is " << *ptr << std::endl;
return 0;
}
运行的结果如下
我们发现int型的指针指向浮点型的数据时并没返回一个正确的结果,主要原因时系统错误的将浮点型的数据当作时整型数据在处理,但是我们发现int指针指向long类型数据时处理有对了,那是因为long和int都是整型数据,所以在解释这种很小的数据的时候,解释的过是一样的,笔者只是在这里举个例子,希望大家不要这样去使用。
5、总结
C++指针的本质是整型数据,声明指针的类型只是告诉系统应该如何处理地址下面的数据。