C/C++ 关于数组和指针的总结
1、数组的声明形如a[d],其中a是数组的名字,d是数组的维度,编译的时候数组的维度应该是已知的,所以维度d必须是一个常量。如果要定义一个不知道元素个数的以为数组,那么请使用vector容器;
unsigned cnt = 42; //不是常量表达式
constexpr unsigned sz = 42; //常量表达式
int arr[10]; //含有10个整数的数组
int *parr[sz]; //含有42个整型指针的数组
string bad[cnt]; //错误:cnt不是常量表达式
string strs[get_size()]; //当get_size()返回值是constexpr时正确
2、一元运算符*和&的优先级比算术运算符的优先级高,因此有:
y = *ip + 1; //把*ip指向的对象的值取出并加1,然后把结果赋值给y
*ip += 1; //将*ip指向的对象的值加1
//等同于
++*ip
//或者
(*ip)++ //此处的圆括号是必须的,否则表达式将对ip加1而不是对ip指向的对象的值加1,因为类似*和++这样的一元运算符遵循从右至左的结合顺序</span>
3、指针与数组的纠缠不清
(1)声明
int a[10]; // 定义了一个长度为10的数组a,这十个整数存储在相邻的内存区域中
int *pa; //定义一个指向整型对象的指针
pa = &a[0]; //将指针指向数组a的第0个元素
int x = *pa; //将数组a[0]的内容复制到变量x中
(2)指针运算:“指针加1”就意味着pa+1指向pa所指向的对象的下一个对象;如果pa指向a[0],那么*(pa+1)引用的是数组元素a[1]的内容,pa+i是数组元素a[i]的地址。
(3)数组名和指针的相同与不同
数组名:a[10],a代表的是该数组的第一个元素的地址,所以pa=&a[0]等价于pa=a。
相同:一个通过数组和下标实现的表达式可以等价地通过指针和偏移量实现
不同:指针是一个变量,因此,语句pa=a和pa++都是合法的,但是数组名不是变量,因此类似a=pa和a++都是非法的。
(4)当把数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址。即将数组作为函数参数传递的时候,会将之转换为一个指针。
在函数定义中,形式参数char s[]和char *s是等价的,我们更习惯于后一种形式。
(5)可以将指向子数组起始位置的指针传递给函数,这样就将数组的一部分传递给了函数。例如,如果a是一个数组,那么f(&a[2])和f(a+2)都将起始于a[2]的子数组的地址传递给函数f。对于函数f来说,它并不关心所引用的是否只是一个更大数组的部分元素。
(6)在定义指针的同时一定要初始化,对指针有意义的初始值是NULL或者是表示地址的表达式,这个表达式必须是在此前已经定义的具有适当类型的数据的地址。
(7)在C语言中,0永远不是有效的数据地址。指向不同数组的元素之间的算术或者比较运算就没有定义,这里有个特例,指针的算术运算中可使用数组最后一个元素的下一个元素的地址。
(8)所有的指针运算,都会自动考虑它所指向的对象的长度,并由此决定p+1以后,p会向前移动几个字节。
4、二维数组的数组名、行指针、指针数组,代码是最有力的说明
(1)在C语言中,二维数组实际上是一种特殊的一维数组,它的每个元素也是一个一维数组
(2)将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明数组的列数。数组的行数没有太大关系。比方说有二维数组daytab[2][13],将这个二维数组传递给函数时,f(int daytab[][13]){……}或者f(int (*daytab)[13]){……},这两种声明方式都可以,后一种更加表明其含义——“参数daytab是一个指针,它指向具有13个整型元素的一维数组”
(3)指针数组和二维数组
int a[10][20];
int *b[10];
从语法角度看,a[3][4]和b[3][4]都是对一个int对象的合法引用。
a是一个真正的二维数组,分配了200个int类型长度的存储空间,并通过常规的矩阵下标计算公式“20*row + col”计算得到a[row][col]的位置。
b,仅仅分配了10个指针,并且没有对它们初始化,如果要跟a[10][20]达到同样的效果,则要在堆上分配200个int类型长度的整数空间,以及栈上10个指针的存储空间
但是:指针数组的一个重要的优点在于,数组的每一行长度可以不同。到目前为止,指针数组最频繁的用处是存放具有不同长度的字符串。
#include <iostream>
using namespace std;
int main()
{
int a[2][2]={1,2,3,4};
//二维数组的本质是数组的数组,所以a+1,这里的步长就会走过那个1维数组的长度,一维数组就是这个二维数组a中的对象
cout << *(*(a+1)) << endl;
//a[0]代表二维数组的第一个元素,即第一行的名字,对它加1,步长是行内元素的大小
cout << *(a[0]+1) << endl;
//a[1]代表二维数组的第二个元素,即第二行的名字
cout << *(a[1]+1) << endl;
//a[0]的类型是int [2],表示含有两个变量的整型数组;
//p的类型是int (*)[2],表示指向“含有两个整型变量的数组”的指针
int (*p)[2] = &a[0];
cout << *(*p+1) << endl;
// q的类型是int *[2],表示含有两个指向整型变量的指针的数组,即数组中元素的类型是整型指针
int *q[2];
q[0] = &a[0][0];
q[1] = &a[1][1];
cout << *q[0] << "\t" << *q[1] <<endl;
return 0;
}
C/C++ 关于数组和指针的总结的更多相关文章
- 把《c++ primer》读薄(4-2 c和c++的数组 和 指针初探)
督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 问题1.我们知道,将一个数组赋给另一个数组,就是将一个数组的元素逐个赋值给另一数组的对应元素,相应的,将一个vector 赋给另 ...
- C语言核心之数组和指针详解
指针 相信大家对下面的代码不陌生: int i=2; int *p; p=&i;这是最简单的指针应用,也是最基本的用法.再来熟悉一下什么是指针:首先指针是一个变量,它保存的并不是平常的数据,而 ...
- 《征服 C 指针》摘录3:数组 与 指针
一.数组 和 指针 的微妙关系 数组 是指将固定个数.相同类型的变量排列起来的对象. 正如之前说明的那样,给指针加 N,指针前进“当前指针指向的变量类型的长度 X N”. 因此,给指向数组的某个元素的 ...
- C指针-数组和指针的归一
int bArr[] = {1,2,3}; int *iarr = bArr; *iarr = 6; printf("%d\n",*iarr); printf("%d\n ...
- 《C专家编程》第四章——令人震惊的事实:数组和指针并不相同
数组和指针是C语言里相当重要的两部分内容,也是新手程序员最容易搞混的两个地方,本章我们锁定指针与数组,探讨它们的异同点. 首先来看指针与数组在声明上的区别: int a[10]; int *p; 很明 ...
- (C语言)数组与指针的区别
以前常常听过这种说法,说数组和指针这两者比较像,但是不能混淆,可是一直没能理解.刚刚在李云的<专业嵌入式软件开发>中,看了讲述数组与指针区别的一章,似乎有所领悟.本着知乎上看到的这张图,我 ...
- C语言教学--二维数组和指针的理解
对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ...
- 【C语言学习】《C Primer Plus》第10章 数组和指针
学习总结 1.数组初始化方式: int a[]={1,2,3} int a[SIZE]={1,2,3} //SIZE是宏定义,数组初始化个数不能大于SIZE,否则报错:当个数小 //SIZE,自动补0 ...
- C语言学习004:数组与指针
在C语言中,字符串实际上就是字符数组,在内存中字符串"Shatner"存储的形式是这样的
- C语言--指向多维数组的指针和指针数组
#include <stdio.h> //void show(char *p[]); ]); int main(){ ][]={","abc","x ...
随机推荐
- k8s记录-安装ansible
##1.安装1) python版本需要2.6以上,不过通过centos7都会默认安装上python2.7.5,查看方法:python -V2) 添加yum 源a.vim /etc/yum.repos. ...
- 在idea中打开maven项目pom.xml未识别
在idea中打开maven项目pom.xml没有识别出来,导致idea不能自动下载依赖包, 解决办法是选中pom.xml文件,右键-" add as maven project"
- EasyNVR摄像机网页无插件直播方案H5前端构建之:通道内部搜索功能的实现方案与代码
EasyNVR网页摄像机直播方案 EasyNVR是一款拥有完整.自主.可控知识产权,同时又能够具备软硬一体功能的安防互联网化流媒体服务器,能够通过简单的网络摄像机通道配置,将传统监控行业里面的高清网络 ...
- Component 'TABCTL32.OCX'错误
1.Component 'TABCTL32.OCX'错误的处理方法 错误:Component 'TABCTL32.OCX' or one of its dependencies not correct ...
- 简单使用Moq框架
Moq框架简单使用 系列目录 Moq库简介及安装 Moq简介 Moq是.net平台下的一个非常流行的模拟库,只要有一个接口它就可以动态生成一个对象,底层使用的是Castle的动态代理功能. 它的流 ...
- Java的三大版本
Java的三大版本 Write Once.Run Anywhere JavaSE:标准版(桌面程序,控制台开发......) JavaME:嵌入式开发(手机,小家电......) JavaEE:E企业 ...
- 90% 前端开发者都不知道的 JavaScript 实用小技巧
面试神器之数组去重 const a = [...new Set([1, 2, 3, 3])] >> [1, 2, 3] 操作数组担心 falsy 值? const res = myArra ...
- Matlab 非线性规划问题模型代码
非线性规划问题的基本内容 非线性规划解决的是自变量在一定的非线性约束或线性约束组合条件下,使得非线性目标函数求得最大值或者最小值的问题. 当目标函数为最小值时,上述问题可以写成如下形式: \[ \mi ...
- [转帖][区块链]共识算法(POW,POS,DPOS,PBFT)介绍和心得
[区块链]共识算法(POW,POS,DPOS,PBFT)介绍和心得 置顶 2017-03-12 18:31:19 乐扣老师lekkoliu 阅读数 127953 收藏 更多 分类专栏: 技术管理 区 ...
- WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因
原文:WPF 的命令的自动刷新时机--当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因 在 WPF 中,你可以使用 Command="{Binding Walt ...