在编程的过程中遇到了很深入的指针之间转换操作,指针的位操作,让我很蒙,这篇文章系统深入的学习一下C++指针类型之间的强制转换,直到学明白为止。
学习后的成果:
char *a="asdasd"; double b= *(double *)&a[0]; • 1 • 2
这段代码虽然只有两句,但并不简单,第一行声明一个char *指针,第二行的意思是
- a[0] 该字符串第一个元素
- &a[0] 该字符串第一个元素的地址,这里相当于char * x = &a[0]
- (double ) &a[0] 将该char指针转换为double *指针 ,相当于double y=(double ) x;
转换前指针是char类型,编译器会找到指针所指向的地址,并每一次取一个字节(char类型元素的大小)将取出来的值按照char类型读取出来;转换后指针是double类型,编译器会找到指针所指向的地址,并每一次取八个字节(double类型元素的大小)将取出来的值按照double类型读取出来 - *(double *)&a[0] 也就是上面所说,取八个字节(double类型元素的大小)将取出来的值按照double类型读取出来
😉一、不同操作系统的基础类型大小
基础类型 | 32位 | 64位 |
bool | 1 | 1 |
char | 1 | 1 |
unsigned char | 1 | 1 |
short int | 2 | 2 |
int | 4 | 4 |
指针 | 4 | 8 |
unsigned int | 4 | 4 |
float | 4 | 4 |
long | 4 | 4 |
unsigned long | 4 | 4 |
double | 8 | 8 |
long long | 8 | 8 |
🐱🐉二、内存中的地址
地址的本质就是一串01机器代码
内存中的地址没有明确数据类型,但地址值有类型
无论什么类型的指针变量,在内存中本质都是一样的,是一个整数值的地址值。
🎉三、内存中的地址没有明确数据类型,但地址值有类型
int *a;
指针变量,本质上是一个变量,只是它是存放地址的变量,指针的类型代表的是它所指向的变量的类型。因此就有了指向整型、字符型、浮点型等其它类型的指针,但实际上所有类型的指针变量存放的都是int型(某一个地址)。
上述代码表示指向整型的指针变量a,其中a表示一个地址值,上面曾提到地址没有明确的数据类型,因为地址可以为指向整型的指针,可以为指向浮点型的指针。指针类型为整型,表示当我们对该地址进行访问(解引用)时,编译器会将它解释为整型。
注意:指针地址只指向数据存储的内存的位置,具体变量的类型由编译器告知。
🐱🚀四、强制转换的原理
(1)普通变量强转
(float)a,就是先按照int类型取出该数值,再将该数值按照int to float的规则转换成float型,如果反过来,则会发生数据截断。
(2)指针变量强转
旧指针 to 新指针的强制类型转换是指将指针所指的内容的类型由原先的类型转换为后面的类型:即进行变量解释的时候,解释的类型变化。
如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP和TYPE,那么语法格式是:(TYPE)p;这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,(也就是说,新指针指向的数据将会用TYPE类型进行解释,如果之前是浮点型数据-3.75,先将其转换为二进制代码,然后转化为TYPE类型存储),它指向的地址就是原指针指向的地址。
🎂五、char*的打印问题!
1.如果给cout提供一个指针,它将打印指针所指向的地址单元的地址,但如果指针类型为char *,则cout将打印char *指针所指向的字符串。
2.如果要显示char *指针所指向的地址单元的地址,需要将char *类型的指针强制转化为另一种类型的指针,我将char *类型的指针强制转化为int *类型指针。
#include "iostream" #include "regex" using namespace std; int main() { char *lpUnitPara = "2111111111111";//lpUnitPara指向字符串的首地址 std::cout << *lpUnitPara << std::endl;// 2 打印首地址的值 std::cout << lpUnitPara[0] << std::endl;// 2 打印第一个元素的值 std::cout << lpUnitPara[1] << std::endl;// 1 打印第二个元素的值 std::cout << &lpUnitPara<< std::endl; //000000061B10F738 打印的是lpUnitPara指针的地址 std::cout << lpUnitPara<< std::endl;//2111111111111 lpUnitPara是字符串的首地址,cout会直接打印lpUnitPara指向的字符串 std::cout << &(lpUnitPara[0]) << std::endl;//2111111111111 lpUnitPara[0]是字符串第一个元素的值,加上&变成了一个char*指针指向第一个元素地址,cout会直接打印该地址指向的字符串 std::cout << &(lpUnitPara[1]) << std::endl;//111111111111 lpUnitPara[1]是字符串第二个元素的值,加上&变成了一个char*指针指向第二个元素地址,cout会直接打印该地址指向的字符串 return 0; }
🥩六、交作业
char *a="asdasd"; double b= *(double *)&a[0];
这段代码虽然只有两句,但并不简单,第一行声明一个char *指针,第二行的意思是
- a[0] 该字符串第一个元素
- &a[0] 该字符串第一个元素的地址,这里相当于char * x = &a[0]
- (double ) &a[0] 将该char指针转换为double *指针 ,相当于double y=(double ) x;
转换前指针是char类型,编译器会找到指针所指向的地址,并每一次取一个字节(char类型元素的大小)将取出来的值按照char类型读取出来;转换后指针是double类型,编译器会找到指针所指向的地址,并每一次取八个字节(double类型元素的大小)将取出来的值按照double类型读取出来 - *(double *)&a[0] 也就是上面所说,取八个字节(double类型元素的大小)将取出来的值按照double类型读取出来
🧊文章总结
提示:这里对文章进行总结:
大彻大悟