c/c++ 指针的江湖传说
万物皆内存,内存有两个东西:地址、值。
普通变量、引用变量、指针变量,二级指针变量,数组,指针数组...等等,皆内存。
【指针】
int x = 10; //变量 int* pX = &x; //指针变量 int** ppX = &pX; //二级指针变量 //地址,值 std::cout << &x << "," << x << std::endl; std::cout << &pX << "," << pX << std::endl; std::cout << &ppX << "," << ppX << std::endl;
x、pX、ppX都是“值”。只不过有的“值”刚好是所指向内存的“地址”,所以课本上、网络上将pX、ppX说成“地址”。
良好的命名习惯,有助于指针的快速理解而不会晕头转向。一级指针p开头,二级指针pp开头,遇*则抵消,遇&则变p。
*pX→x,值 10
*ppX→pX,值 00000086ECBBF604
**ppX→x,值 10
&x→pX,值 00000086ECBBF604
&pX→ppX,值 00000086ECBBF648
&ppX→pppX,值 00000086ECBBF668
【指针大小,地址存储与取值】
开篇图中,只有10是int型,占4字节。其他的5个“值”“地址”都是地址属性,64位系统中占8字节,32位系统中占4字节。
为了稳妥,可以用 long long承接地址。下面将图中的5个地址存入数组,取值时先转类型再取值。
long long y[5]; y[0] = (long long)&x; //pX y[1] = (long long)pX; y[2] = (long long)&pX; //ppX y[3] = (long long)ppX; y[4] = (long long)&ppX; //pppX std::cout << *(int*)y[0] << std::endl; //*(int*)pX,由于pX是int*类型,所以先转换为int*类型,然后再取值,即*pX→x std::cout << *(int*)y[1] << std::endl; std::cout << **(int**)y[2] << std::endl; //**(int**)ppX,ppX是int**类型,所以先转类型再取值,即**ppX→x std::cout << **(int**)y[3] << std::endl; std::cout << ***(int***)y[4] << std::endl; //***(int***)pppX,先转类型再取值,即***pppX→x
在实际项目中的应用:
相机帧数据量较大,一般传递帧地址(const unsigned char*),在需要的地方拿到这个地址即可。
unsigned char pixelData = 255; const unsigned char* pBuffer=&pixelData;//所以帧地址不变,值会一直变,即像素数据 long long val; //拉流回调函数里获取帧地址 val = (long long)pBuffer; //传到某个用到帧的地方 unsigned char* pImg = (unsigned char*)val;
【数组】
数组,不同类型的存取 - 夕西行 - 博客园 (cnblogs.com)
【函数传参,指针参数】