[ 随手记 2 ] C/C++ 数组/指针/传数组到函数/指针数组/数组指针
1.===================================================================
1,数组是一块内存连续的数据。
2,指针是一个指向内存空间的变量。 对于数组来说,数组的首地址,也可以用指针来表示操作,如:
int a[10];
int *p,n;
p = a;
对第一个元素取值,可以用几种方法:
n =a[0];
n = *p;
n = p[0];
n = *(p+0) ; 对第i个元素取值,可以用:
n = a[i];
n = p[i];
n = *(p+i); 3,不同的地方是数组是由编译器分配的空间,变量名是不能再赋值的;而指针是可以重复赋值的(除定义为const)
如:
p = a; //正确
a = p; //错误 2.==================================================================================================
在c语言中,指针和数组名都表示地址,但两者却有很大的不同之处,对于初学者来说一定要弄清楚两者的区别。
首先,我举个简单的例子:
char *p1="hello!"; //定义字符型指针p1,并将指针p1指向字符串“hello!”的首地址。
char s[10]="hello!"; //定义数组s,并将其初始化赋值。
然而,如果char s[10]; s="hello!";这样就会报错,为什么呢?原因很简单,因为数组名是常量。
言归正传,我现在举两个简单的例子:
例子1
void main()
{
char p[]="abcdef";
p[0]='Y';
printf("%s",p);
}
在本段程序中输出Ybcdef
例子2
void main()
{
char *p="abcdef";
p[0]='Y';
printf("%s",p);
}
本段程序却抛出异常,为什么?
在例子2中,char *p="abcdef",指针p是存储在堆栈区,但字符串是常量,存储在常量区,只是指针p指向了存储在常量区的字符串首地址,此时不能改变常量区的字符串的值。
在例子1中,char p[]="abcdef",此处的赋值是将常量区的字符串“abcdef”拷贝到了堆栈区的数组p的空间了。数组p是在堆栈区开辟了空间,此时是可以修改 字符串的值,因为修改的是堆栈区的字符串的值。另外此时的数组名p是堆栈区中的”abcdef“的首地址。
3.======================================================================
c++不允许向函数传递一个完整的数组作为参数,但是用户可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针
如果想要在函数中传递一个一维数组作为参数,用户必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编辑器将要接受一个整型指针,同样的,用户也可以传递一个多维数组作为形式参数
方式1
void myFunction (int *param)
{
}
形式参数是一个指针
方式2
void myFunction (int param[10])
{
}
形式参数是一个已定义大小的数组
方式3
void myFunction(int param[])
{
}
形式参数是一个未定义大小的数组
ps: 其实上述三种方式传给函数的都是数字的首地址,也就是指向首地址的一个指针.
4.=======================================================================
一维数组
在c和c++中数组的指针就是数组的起始地址(也就第一个元素的地址),而且标准文档规定数组名代表数组的地址(这是地址数值层面的数组表示)。例如:
int a[10];
int *p;
p=&a[0]//和p=a是等价的。
因为a是数组名,所以他是该数组的地址,同时因为第一个元素为a[0],那么&a[0]也代表了该数组的地址。但是我们是不是就说一个数组 名 和该数组的第一个元素的&运算是一回事呢?在一维的时候当时是的,但是在高维的时候,我们要考虑到维数给数组带来的影响。
a[10]是一个数组,a是数组名,它是一个包含10个int类型的数组类型,不是一般的指针变量噢!(虽然标准文档规定在c++中从int[]到 int*直接转换是可以的,在使用的时候似乎在函数的参数为指针的时候,我们将该数组名赋值没有任何异样),a代表数组的首地址,在数字层面和a[10] 的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。
所以我们要注意以下问题:
- p[i]和a[i]都是代表该数组的第i+1个元素;
- p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用 *(p+I)和*(a+I)来引用对象元素;
- p+1不是对于指针数量上加一,而是表示从当前的位置跳过当前指针指向类型长度的空间,对于win32的int为4byte;
多维数组
对于二维数组a[4][6];由于数组名代表数组的起始地址,所以a(第一层)和第一个元素a[0][0]地址的数字是相同的,但是意义却是不同
的。
对于该数组我们可以理解为:a的一维数组(第一层),它有四个元素a[0]、a[1]、a[2]、a[3](第二层),而每个元素又含有6个元素a[0]
[0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三层),…到此我们终于访问到了每个元素了,这个过程我们
经历了:a->a[0]->a[0][0];
整体来讲:a是一个4行6列的二维数组,a表示它指向的数组的首地址(第一个元素地址&a[0]),同时a[0]指向一行,它是这个行的名 字 (和该行的第一个元素的首地址相同(第一个元素为地址&a[0][0]))。所以从数字角度说:a、a[0]、&a[0][0]是相同 的,但是他们所处的层次是不同的。
既然a代表二维数组,那么a+i就表示它的第i+1个元素*(a+i)的地址,而在二维数组中
*(a+i)又指向一个数组,*(a+i)+j表示这个数组的第j+1个元素的地址,所以要访问这个元素可以使用 *(*(a+i)+j)(也就是a[i][j])。
5.======================================================================================
指针数组与数组指针
两者的理解可以认为重点后面的名词:
(1)即指针数组本质是一个数组,数组元素为指针类型;
(2)数组指针本质上是一个指针,该指针指向一个数组;
在指针数组中如下代码:
- #include<stdio.h>
- int main(void)
- {
- char **p, i;
- char *strings[] ={
- "one",
- "two",
- "three"
- };
- p=strings; //strings是地址的地址,所以要定义**p
- for(i=0; i<3; i++)
- printf("%s\n", *(p++)); //这里*(p++)是取出存储在数组中的每一个字符串的地址
- return 0;
- }
这里创建了一个指针数组strings,它的每个数组元素相当于一个指针变量,都可以指向一个整形变量,其值为地址。也就是说strings数组中每个元素存放的是字符串的地址。
这里可以将指针数组看成 * (strings[1])之类,后面的那部分 strings[1] 看成指针变量 p.
数组指针( (*strings)[] )
数组指针,指的是数组名的指针,即数组首元素地址的指针。即是指向数组的指针。例:int (*p)[10]; p即为指向数组的指针,又称数组指针。
- int a[4][5];
- int (*p)[5]=a;
这里所代表的 *(p+i) 是二维数组a[i][0]的地址。
[ 随手记 2 ] C/C++ 数组/指针/传数组到函数/指针数组/数组指针的更多相关文章
- C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)
严格来说这篇文章算不上C++范围的,不过还是挂了点边,还是在自己的blog中记录一下吧. C++中使用指针是家常便饭了,也非常的好用,这也是我之所以喜欢C++的原因之一.但是在C#中就强调托管的概念了 ...
- c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配
一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...
- [ 随手记6 ] C/C++ 形参、实参、按值传参、指针传参、引用传参
个人原创: 1. 形参:形式上的参数,一般多在函数声明.函数定义的参数上: 2. 实参:实体参数,有实际的值,在运算上被循环使用的值: 3. 按值传参:按值,就是把实际的值传给函数内部: 4. 指针传 ...
- c/c++ 函数、常量、指针和数组的关系梳理
压力才有动力,15年中旬就要准备实习,学习复习学习复习学习复习学习复习……无限循环中,好记性不如烂笔头……从数组开始,为主干. c 的array由一系列的类型相同的元素构成,数组声明包括数组元素个数和 ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- C语言中,数组名作为参数传递给函数时,退化为指针
C语言中,数组名作为参数传递给函数时,退化为指针 C语言中,数组名作为参数传递给函数时,退化为指针:需要数组大小时, 需要一个参数传数组名,另一个传数组大小. 数组名做函数参数时,就相当于指针了. ...
- 指针数组与带参main函数
(一)指针数组 指针数组就是每一个元素存放一个地址,相当于一个指针变量.如:int *p[4]指针数组比较适合用来指向若干字符串,使得处理字符串更加灵活.例如,现在要将若干字符串按字母顺序由小到大输出 ...
- 【Go入门教程5】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- Delphi下使用指针的简单总结(指针的赋值,数组和指针的转换,函数指针的使用)
由于最近公司太忙,好久没有更新我的BLOG了.原来想着写写关于HOOK驱动的文章,可是最后想想好久已经没有做驱动的东西了,怕写出来有错误,于是作罢.开发游戏也有一段时间了,发现使用DELPHI来开发网 ...
随机推荐
- iframe的缺点
*iframe会阻塞主页面的Onload事件: *搜索引擎的检索程序无法解读这种页面,不利于SEO; *iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载. 使用i ...
- Linux中安装tomcat后,window中访问不到tomcat的欢迎界面问题
首先,可以通过xftp把下载的tomcat的tar.gz包传输到Linux中. 然后进行解压,tar -zxvf tomcat的压缩包名称(可以使用tab键快速补齐) 解压后,可以使用修改/con ...
- MySQL—概念,用户的创建,主键,外键,数据类型,表格创建
MySQL DBMS,MySQL的概念,数据库分类,以前MySQL的部署中的一些概念 #DBMS:数据库管理系统,用于管理数据库的大型软件.mysql就是dbms的一种 #Mysql:是用于管理文件的 ...
- linux TOP参数
TOP参数 top - 01:06:48 up 1:22, 1 user, load average: 0.06, 0.60, 0.48Tasks: 29 total, 1 running ...
- 关于async 中return 和 return await 的差异
小七平时在使用ES2017的 async功能经常会有如下: const bluebird = require('bluebird'); async function doSomething() { a ...
- EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
前言 α角 与 β角 关于α角 与 β角的介绍,请见上文 如何用EFCore Lazy Loading实现Entity Split. 本篇会继续有关于β角的彩蛋在等着大家去发掘./斜眼笑 其他 本篇的 ...
- JDBC Request
1.下载jdbc驱动,放至jmeter安装目录的lib目录和lib\ext目录下 PS:自己操作的时候,由于JDBC Connection Configuration中驱动名称写错,前面多了一个空格, ...
- xml的作用
XML应用面主要分为两种类型,文档型和数据型.下面介绍一下几种常见的XML应用: 1.自定义XML+XSLT=>HTML,最常见的文档型应用之一.XML存放整个文档的XML数据,然后XSLT将X ...
- Django中views笔记
reverse反解析 #路由中定义namespace.name,reverse可将其转换为url url = reverse('namespace:name') return redirect(url ...
- MySQL行转列、列转行
一.行转列 有如图所示的表,现在希望查询的结果将行转成列 建表语句如下: CREATE TABLE `TEST_TB_GRADE` ( `ID` int(10) NOT NULL AUTO_INCRE ...