1. 什么是指针变量?

指针变量是专门有一个变量来存放指针。

int main(int argc, char *argv[])
{int a = 10;int *p = &a;    //通过取地址符号 & 把 a 变量的地址传给指针变量 pstd::cout << "p is " << p << std::endl;     // p is 0x7fffe740301cstd::cout << "&a is " << &a << std::endl;   //&a is 0x7fffe740301cstd::cout << "*p=" << *p << std::endl;      // *p=10return 0;
}

通过符号 *p 获取指针变量 p 指向的地址的存放的值。我们可以理解为通过变量 p 我们拿到抽屉的钥匙(地址)打开抽屉取出数据。

int main()
{int i = 3;int *iptr = &i;int **iptrptr = &iptr;  //iptr 也是变量,也能够获取它的地址cout << "iptr=" << iptr <<endl;  //输出 iptr 存储的内容,即 i 在内存中的地址cout << "*iptr=" << *iptr <<endl;    //输出 iptr 所指向的变量cout << "iptrptr=" << iptrptr <<endl;    //输出 iptr 在内存中的地址cout << "*iptrptr=" << *iptrptr <<endl;  //输出 iptrptr 所指向的变量,即 iptr*iptr = 2 + *iptr;  //*iptr 可以作左值cout << "*iptr=" << *iptr <<endl;return 0;
}

输出结果:

iptr=0x7ffd0e00e2b4
*iptr=3
iptrptr=0x7ffd0e00e2b8
*iptrptr=0x7ffd0e00e2b4
*iptr=5

2. 数组和指针

int main(int argc, char *argv[])
{int a[3] = {1,2,3};int *p = a;std::cout << "p is " << p << std::endl;    std::cout << "&a is " << &a << std::endl;   std::cout << "a is " << a << std::endl;    std::cout << "&a[0] is " << &a[0] << std::endl;     std::cout << "*p=" << *p << std::endl;      std::cout << "*(p+1)=" << *(p+1) << std::endl;     std::cout << "a[1]=" << a[1] << std::endl;  return 0;
}

执行输出结果:

p is 0x7fff7b96be40
&a is 0x7fff7b96be40
a is 0x7fff7b96be40
&a[0] is 0x7fff7b96be40
*p=1
*(p+1)=2
a[1]=2

a 的值就是数组 a 第一个元素的地址,与 &a[0]&a 等价。

而 p+1 表示的是数组 a 的第二个元素的地址,以此类推。

获取数组的第二个元素可以是 a[1],也可以是 *(p+1)。

3. 指针数组

表示数组内存放的是指针类型的数据。

定义方式

int *p[]:

示例:

int main(int argc, char *argv[])
{int a[3] = {1,2,3};int *p[3] = {a,a+1,a+2};std::cout << "a= " << a << std::endl;     std::cout << "a+1= " << a+1 << std::endl;   std::cout << "a+2= " << a+2 << std::endl;  std::cout << "*p=" << *p << std::endl;      std::cout << "*(p+1)=" << *(p+1) << std::endl;   std::cout << "p[1]=" << p[1] << std::endl;    std::cout << "**p=" << **p<< std::endl;  std::cout << "**(p+1)=" << **(p+1) << std::endl;  return 0;
}

输出:

a= 0x7ffd747a1b70
a+1= 0x7ffd747a1b74
a+2= 0x7ffd747a1b78
*p=0x7ffd747a1b70
*(p+1)=0x7ffd747a1b74
p[1]=0x7ffd747a1b74
**p=1
**(p+1)=2

aa+1a+2 分别表示数组 a 第一个、第二个、第三个元素的地址。

p+1 指的是指针数组 p 的第二个元素的地址,而 *(p+1)(等价于 p[1])指的就是第二个元素地址存放的值,也就是 a+1

a+1*(p+1) 值是相等的。

4. 数组指针

表示指针是数组类型的,就像 int 类型指针,char 类型指针一样。
定义方式:

int (*p)[n]

() 优先级高,首先说明 p 是一个指针,指向一个整型的一维数组,这个一维数组的长度是 n,也可以说是 p 的步长。

示例:

int main(int argc, char *argv[])
{int a[3] = {1,2,3};int (*p)[3] = &a;   //定义一个指向长度为 3 的 int 数组的指针std::cout << "a  = " << a << std::endl;     std::cout << "a+1= " << a+1 << std::endl;   std::cout << "p+1= " << p+1 << std::endl; std::cout << "a+2= " << a+2 << std::endl;  std::cout << "&a= " << &a << std::endl; std::cout << " p= " << p << std::endl;  std::cout << "*p= " << *p << std::endl;  return 0;
}

输出:

a  = 0x7ffd63226b30
a+1= 0x7ffd63226b34
p+1= 0x7ffd63226b3c
a+2= 0x7ffd63226b38
&a= 0x7ffd63226b30p= 0x7ffd63226b30
*p= 0x7ffd63226b30

&aap 值是相等的,都是指数组 a 的第一个元素的地址。

仔细看两个值,可以发现 p+1(0x7ffd63226b3c)是 p(0x7ffd63226b30)再加 12,也就是数组 a 所有元素加起来的长度(长度 3*int 类型的 4 个字节),所以数组指针 p 再加 1,这里的 1 指的就是数组 a 所有元素加起来的长度,而不是数组元素的长度。

p*p 两个值是一样的。*p 的值是数组 a 第一个元素的地址,而 p 虽然也是数组 a 第一个元素的地址,但是 p 指的是整个数组的地址,只是用了数组 a 的第一个元素地址来替代,而 *p 是指这个数组的地址对应的值,就是数组本身,
也就是 a,而 a 的值也就是数组 a 第一个元素的地址,所以 *p 等于 a

int a[3] = {1,2,3};
int (*p)[3] = &a;
cout<<**p<<endl;
cout<<*(*p+1)<<endl;
cout<<(*p)[1]<<endl;

输出:

1
2
2

*p 表示数组第一个元素地址,**p 表示数组第一个元素地址存放的值也就是 1;p+1 表示数组第二元素地址,(*p+1) 表示数组第二个元素地址存放的值也就是 2。(*p)[1] 与 *(*p+1) 值一样,都是表示数组第二个元素值,即 a[1]。

如果改成下面:

int main(int argc, char *argv[])
{int a[3] = {1,2,3};int (*p)[3] = a;   return 0;
}

会编译报错:

cannot convert ‘int*’ to ‘int (*)[3]’ in initialization

因为 a 这里是一维数组,a 代表的是数组 a 首个元素地址,而不是整个数组地址。

假设 a 数组是二维数组,如下定义:

int main(int argc, char *argv[])
{int a[2][3] = {{1,2,3},{4,5,6}};int (*p)[3] = &a; return 0;
}

会编译报错:

cannot convert ‘int (*)[2][3]’ to ‘int (*)[3]’ in initialization

因为这里 a 是二维数组,而 &a 表示整个二维数组的地址,是包含 2*3=6 个元素的数组。那要怎么改才可以呢?

可以改成:

int (*p)[3] = a; // 这里 a 理解为二维数组 a 第一维 a[0][]数组的地址。

或者改为:

int (*p)[2][3] = &a; // 表示2行3列的二维数组地址

完整代码:

int main(int argc, char *argv[])
{int a[2][3] = {{1,2,3},{4,5,6}};int (*p)[3] = a;   std::cout << "a= " << a << std::endl;     std::cout << "a+1= " << a+1 << std::endl;   std::cout << "a+2= " << a+2 << std::endl;  std::cout << "&a=" << &a << std::endl; std::cout << "p=" << p << std::endl;      std::cout << "*(p+1)=" << *(p+1) << std::endl;   std::cout << "p[1]=" << p[1] << std::endl;    std::cout << "**p=" << **p<< std::endl;  std::cout << "**(p+1)=" << **(p+1) << std::endl;     return 0;
}

输出结果:

a= 0x7ffe52d671f0
a+1= 0x7ffe52d671fc
a+2= 0x7ffe52d67208
&a=0x7ffe52d671f0
p=0x7ffe52d671f0
*(p+1)=0x7ffe52d671fc
p[1]=0x7ffe52d671fc
**p=1
**(p+1)=4

5. 指针常量与常量指针

int main()
{int a = 42;const int b = 84;const int *c_a_ptr = &a;    //常量指针int * const a_c_ptr = &a;   //指针常量int *b_ptr = &b;            //错误,不能把常量的地址给指针变量const int *c_b_prt = &b;    //把常量的地址给常量指针是允许的*c_a_ptr = 68;              //错误,间接引用常量指针不可修改内存中的数据*a_c_ptr = 68;              //间接引用指针常量可以修改内存中的数据c_a_ptr = &b;               //常量指针可以指向其他变量a_c_ptr = &b;               //错误,指针常量不能指向别的变量const int * const c_c_a_ptr = &a;   //常量指针常量,既不能间接引用修改数据,也不能指向别的变量或常量*c_c_a_ptr = 68;            //错误,不能间接引用修改数据c_c_a_ptr = &b;             //错误,不能指向别的常量或变量return 0;
}

C++ 笔记(27)— 指针变量、数组和指针、指针数组、数组指针、指针常量与常量指针相关推荐

  1. c语言多维数组指针地址讲解,C语言入门之多维数组的指针变量

    一.多维数组地址的表示方法 设有整型二维数组a[3][4]如下: 0 1 2 3 4 5 6 7 8 9 10 11 设数组a的首地址为1000,各下标变量的首地址及其值如图所示. 在前面曾经介绍过, ...

  2. C程序设计基础之多维数组的指针变量

    一.多维数组地址的表示方法 设有整型二维数组a[3][4]如下: 0 1 2 3 4 5 6 7 8 9 10 11 设数组a的首地址为1000,各下标变量的首地址及其值如图所示.    在前面曾经介 ...

  3. 动态二维数组外圈元素值的和_C语言 | 用指向元素的指针变量输出二维数组元素的值...

    例33:有一个3*4的二维数组,要求用C语言实现指向元素的指针变量输出二维数组个元素的值. 解题思路:二维数组的元素时整型的,它相当于整型变量,可以用int*型指针变量指向它.二维数组的元素在内存中是 ...

  4. C语言中数组变量和指针变量

    指针变量为什么需要类型? 数组变量和指针变量在使用sizeof时不同,sizeof(数组变量)是数组长度,sizeof(指针变量)是存储int的字节长度4或者8(64bit). 数组变量在参数传递中, ...

  5. 字符指针变量和字符数组的对比

    使用字符数组和指针变量都能实现字符串的存储和运算,但它们两者之间是有区别的,不应混为一谈,主要有一下几点: (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串中 ...

  6. 第三节 数组的指针和指向数组的指针变量

    目录 一.指向数组元素的指针变量的定义和赋值 二.通过指针引用数组元素 三.数组名作为函数参数 四.指向多维数组的指针和指针变量探究 五.指针数组和数组指针 一.指向数组元素的指针变量的定义和赋值 数 ...

  7. 字符指针变量和字符数组的比较

    用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点. (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串 ...

  8. 【C 语言】字符串拷贝 ( 函数形参使用推荐方法 | 凡是涉及 修改指针指向 的操作一律创建新的 指针变量 执行 | 引入 辅助 局部 指针变量 )

    文章目录 一.函数形参使用推荐方法 二.完整代码示例 一.函数形参使用推荐方法 在函数中 , 形参 中的 指针变量 , 不建议直接使用 ; 推荐 在 函数中 , 定义 局部 指针变量 , 接收 形参中 ...

  9. c语言字符指针初始化赋值,C语言_指针变量的赋值与运算,很详细详解

    指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...

  10. C 温故知新 之 指针:函数指针变量、指针型函数

    猛一看还真有点糊糊:注意区别: 1.函数型指针:指函数返回值的类型.    指针型函数:返回值是一个指针(即地址)   2.int(*p)()和int *p() 是一样吗?为什么?  int (*p) ...

最新文章

  1. log_sum_exp
  2. OpenGL之glMatrixMode函数的用法
  3. 【编译原理】让我们来构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 1.)(python/c/c++版)(笔记)
  4. php中的意外type字符串,关于php:解析错误:语法错误,意外’文本’(T_STRING),期待’,’或’;’...
  5. C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)
  6. 让动画每次重复前都有延迟
  7. 总线驱动:Bus driver - USB driver for example
  8. 吴恩达|机器学习作业7.1.主成分分析(PCA)
  9. 产品经理与交互设计师的对话——需求是如何变成产品原型的(转)
  10. Python 进阶 —— 重访 tuple
  11. linux mysql 卸载,安装,测试全过程
  12. linux怎么用jconsole_linux中jconsole
  13. 连续多帧图像光流对齐和光流运动检测
  14. 上海康桥先进制造技术创业园项目远程预付费系统的应用-安科瑞耿敏花
  15. 无刷直流电动机矢量控制(四)——simulink仿真搭建(让电机动起来)
  16. 【AAE】【Keras】实现merge出错:TypeError: ‘module‘ object is not callable
  17. 如何用easyx播放音乐,插入图片
  18. 银联手机网页如何调用云闪付(银联钱包)
  19. linux库函数pthread.h------pthread_rwlock_t读写锁说明
  20. docker制作镜像的两种方法

热门文章

  1. 2022-2028年中国防臭袜行业投资分析及前景预测报告
  2. 【Sql Server】DateBase-视图
  3. Electron、QT和JAVA PC桌面开发技术比较
  4. 正则表达式中?=和?:和?!的理解
  5. 分治算法的设计思想(二分检索、二分归并排序)
  6. LeetCode简单题之公平的糖果交换
  7. IP 公司与GPU IP
  8. IP SOC与Camera ISP
  9. deeplearning模型分析
  10. 微调torchvision 0.3的目标检测模型