C++ 笔记(27)— 指针变量、数组和指针、指针数组、数组指针、指针常量与常量指针
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
a
、a+1
、a+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
&a
与 a
、p
值是相等的,都是指数组 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)— 指针变量、数组和指针、指针数组、数组指针、指针常量与常量指针相关推荐
- c语言多维数组指针地址讲解,C语言入门之多维数组的指针变量
一.多维数组地址的表示方法 设有整型二维数组a[3][4]如下: 0 1 2 3 4 5 6 7 8 9 10 11 设数组a的首地址为1000,各下标变量的首地址及其值如图所示. 在前面曾经介绍过, ...
- C程序设计基础之多维数组的指针变量
一.多维数组地址的表示方法 设有整型二维数组a[3][4]如下: 0 1 2 3 4 5 6 7 8 9 10 11 设数组a的首地址为1000,各下标变量的首地址及其值如图所示. 在前面曾经介 ...
- 动态二维数组外圈元素值的和_C语言 | 用指向元素的指针变量输出二维数组元素的值...
例33:有一个3*4的二维数组,要求用C语言实现指向元素的指针变量输出二维数组个元素的值. 解题思路:二维数组的元素时整型的,它相当于整型变量,可以用int*型指针变量指向它.二维数组的元素在内存中是 ...
- C语言中数组变量和指针变量
指针变量为什么需要类型? 数组变量和指针变量在使用sizeof时不同,sizeof(数组变量)是数组长度,sizeof(指针变量)是存储int的字节长度4或者8(64bit). 数组变量在参数传递中, ...
- 字符指针变量和字符数组的对比
使用字符数组和指针变量都能实现字符串的存储和运算,但它们两者之间是有区别的,不应混为一谈,主要有一下几点: (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串中 ...
- 第三节 数组的指针和指向数组的指针变量
目录 一.指向数组元素的指针变量的定义和赋值 二.通过指针引用数组元素 三.数组名作为函数参数 四.指向多维数组的指针和指针变量探究 五.指针数组和数组指针 一.指向数组元素的指针变量的定义和赋值 数 ...
- 字符指针变量和字符数组的比较
用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点. (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串 ...
- 【C 语言】字符串拷贝 ( 函数形参使用推荐方法 | 凡是涉及 修改指针指向 的操作一律创建新的 指针变量 执行 | 引入 辅助 局部 指针变量 )
文章目录 一.函数形参使用推荐方法 二.完整代码示例 一.函数形参使用推荐方法 在函数中 , 形参 中的 指针变量 , 不建议直接使用 ; 推荐 在 函数中 , 定义 局部 指针变量 , 接收 形参中 ...
- c语言字符指针初始化赋值,C语言_指针变量的赋值与运算,很详细详解
指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...
- C 温故知新 之 指针:函数指针变量、指针型函数
猛一看还真有点糊糊:注意区别: 1.函数型指针:指函数返回值的类型. 指针型函数:返回值是一个指针(即地址) 2.int(*p)()和int *p() 是一样吗?为什么? int (*p) ...
最新文章
- log_sum_exp
- OpenGL之glMatrixMode函数的用法
- 【编译原理】让我们来构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 1.)(python/c/c++版)(笔记)
- php中的意外type字符串,关于php:解析错误:语法错误,意外’文本’(T_STRING),期待’,’或’;’...
- C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)
- 让动画每次重复前都有延迟
- 总线驱动:Bus driver - USB driver for example
- 吴恩达|机器学习作业7.1.主成分分析(PCA)
- 产品经理与交互设计师的对话——需求是如何变成产品原型的(转)
- Python 进阶 —— 重访 tuple
- linux mysql 卸载,安装,测试全过程
- linux怎么用jconsole_linux中jconsole
- 连续多帧图像光流对齐和光流运动检测
- 上海康桥先进制造技术创业园项目远程预付费系统的应用-安科瑞耿敏花
- 无刷直流电动机矢量控制(四)——simulink仿真搭建(让电机动起来)
- 【AAE】【Keras】实现merge出错:TypeError: ‘module‘ object is not callable
- 如何用easyx播放音乐,插入图片
- 银联手机网页如何调用云闪付(银联钱包)
- linux库函数pthread.h------pthread_rwlock_t读写锁说明
- docker制作镜像的两种方法