指针数组

图解c/c++多级指针与“多维”数组

北城余情 提交于 2019-12-19 23:22:28
声明: 本文为原创博文,如有转载,请注明出处。若本文有编辑错误、概念错误或者逻辑错误,请予以指正,谢谢。 指针与数组是C/C++编程中非常重要的元素,同时也是较难以理解的。其中,多级指针与“多维”数组更是让很多人云里雾里,其实,只要掌握一定的方法,理解多级指针和“多维”数组完全可以像理解一级指针和一维数组那样简单。 首先,先声明一些常识,如果你对这些常识还不理解,请先去弥补一下基础知识: 1、实际上并不存在多维数组,所谓的多维数组本质上是用一维数组模拟的。 2、数组名是一个常量(意味着不允许对其进行赋值操作),其代表数组首元素的首地址。 3、数组与指针的关系是因为数组下标操作符[],比如,int a[3][2]相当于*(*(a+3)+2) 。 4、指针是一种变量,也具有类型,其占用内存空间大小和系统有关,一般32位系统下,sizeof(指针变量)=4。 5、指针可以进行加减算术运算,加减的基本单位是sizeof(指针所指向的数据类型)。 6、对数组的数组名进行取地址(&)操作,其类型为整个数组类型。 7、对数组的数组名进行sizeof运算符操作,其值为整个数组的大小(以字节为单位)。 8、数组作为函数形参时会退化为指针。 一、一维数组与数组指针 假如有一维数组如下: char a[3]; 该数组一共有3个元素,元素的类型为char,如果想定义一个指针指向该数组

5种智能指针指向数组的方法| 5 methods for c++ shared_ptr point to an array

半世苍凉 提交于 2019-12-19 12:55:13
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 本文首发于个人博客 https://kezunlin.me/post/b82753fc/ ,欢迎阅读最新内容! 5 methods for c++ shared_ptr point to an array <!--more--> Guide shared_ptr Prior to C++17 , shared_ptr could not be used to manage dynamically allocated arrays. By default, shared_ptr will call delete on the managed object when no more references remain to it. However, when you allocate using new[] you need to call delete[] , and not delete , to free the resource. In order to correctly use shared_ptr with an array, you must supply a custom deleter. code example //OK, pointer to int 999 std::shared_ptr

C++day05 学习笔记

南楼画角 提交于 2019-12-19 12:45:16
1、变量的存储 (1)内存是一块空间,把其中的每个字节做了编号,为了以后计算机能通过编号找到数据 (2)编址方式:绝对编址(在整个程序中使用),相对编址(字节相对于逻辑0偏移量,在进程中使用) 2、取变量地址 (1)"&" &i 表示取内存中i的地址 地址的编址用十六进制表示 (2)逻辑0在代码区 全局变量在数据区,地址的编址是大于0的 局部变量在栈区,地址的编址是小于0的 3、数组、结构的地址 (1)数组中的数据在内存中是连续存储的。 数组中每个元素的地址相差的值应为数组元素类型的大小。 (2)结构的地址: 结构的空间是连续的。 结构的起始地址与第一个成员变量的地址是一样的。 4、存储地址— 指针:存储变量的地址 指针的类型由将要保存的地址的变量类型决定 int*只能保存int变量的地址 指针赋值一定要是同类型的指针才能相互赋值! 5、指针的运算 (1)指针和指针之间的运算 “+”,“*”,“/” 指针与指针间是不能做这些运算,没有意义! “-” 可以做减法运算,以“sizeof(指针类型)”作为计算单位的! 注意:要同类型的指针才能做此运算,不同的话,会对运算单位产生歧义。 (2)指针和数字之间的运算(加、减都可以) int i = 100; int * p = &i; 打印 p+1 -> 相当于在地址上加4,因为存储的变量是int类型的 p+2 -> 相当于在地址上加8 6

C语言第八讲,指针*

人盡茶涼 提交于 2019-12-19 00:33:58
            C语言第八讲,指针* 一丶简单理解指针 说到指针,很多人都说是C语言的重点. 也说是C语言的难点. 其实指针并不是难.而是很多人搞不清地址 和 值.以及指针类型. 为什么这样说. 假设有两个变量,如下 int nNum1 = 1; int nNum2 = 0x00401000; 变量nNum1 保存的值是1 变量nNum2 保存的是一个16进制数值. 那么如果我们把保存16进制的这个变量.当作指针. 也就是说它保存了一个16进制数值而已. 我们可以通过16进制找到里面存储的值. 但是因为是保存地址的变量.所以我们需要加上特殊符号进行定义. 例如:    int *nNum2 = 0x004010000; 指针其实就是保存了一个特殊的数值而已. 而通常这个数值我们说是地址. 如果我们保存了1的地址,那么我们就可以访问1了. 怎么访问? 可以通过取内容符号进行访问. int nNum = 1; int *p = &nNum1; //保存1的地址,我们可以不用管.也可以理解为一个16进制数值而已. *p = 3; //修改地址空间的值. 二丶指针的数据类型 说到指针.其实我们说的并不是保存地址的难点.难点是该如何解释这个地址. 例如我们知道定义一个变量.我们可以知道这个变量的内存空间跟随这数据类型走. 例如:    int nNum1 = 3; //nNum1

C指针右左法则

荒凉一梦 提交于 2019-12-18 21:32:22
摘录的别人的: C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的: The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed. 这段英文的翻译如下: 右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。 笔者要对这个法则进行一个小小的修正

字符数组,字符指针,Sizeof总结

痞子三分冷 提交于 2019-12-18 09:56:35
字符数组,字符指针,Sizeof总结 1.以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写 "abc",那么编译器帮你存储的是"abc\0" 2."abc"是常量吗?答案是有时是,有时不是。 不是常量的情况:"abc"作为字符数组初始值的时候就不是,如 char str[] = "abc"; 因为定义的是一个字符数组,所以就相当于定义了一些空间来存放"abc",而又因为 字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为 char str[3] = {'a','b','c'}; 又根据上面的总结1,所以char str[] = "abc";的最终结果是 char str[4] = {'a','b','c','\0'}; 做一下扩展,如果char str[] = "abc";是在函数内部写的话,那么这里 的"abc\0"因为不是常量,所以应该被放在栈上。 是常量的情况: 把"abc"赋给一个字符指针变量时,如 char* ptr = "abc"; 因为定义的是一个普通指针,并没有定义空间来存放"abc",所以编译器得帮我们 找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器 最合适的选择。所以尽管ptr的类型不是const char*,并且ptr[0] = 'x';也能编译 通过,但是执行ptr[0] =

数据结构与算法(六)循环队列——顺序存储结构

孤者浪人 提交于 2019-12-18 01:28:39
循环队列 先不急着给循环队列的定义,先看队列循环存储结构的弊端。 队列顺序存储结构的弊端 队列的顺序存储结构本身是由ArrayList实现的,在数据元素入队的时候,相当于在ArrayList表尾添加元素,在数据元素出队的时候,相当于在ArrayList表头删除元素。很明显,入队的时间复杂度O(1),出队的时间复杂度O(n),线性表增删数据元素时间复杂符都是O(n),但是这个是按平均算的。队列的出队时间复杂度O(n),可不是按平均算的,因为每次出队都是O(n)。 有弊端,就可以换其他思路进行优化 优化一 :为了避免当只有一个元素时,队头队尾重合处理变得麻烦,所有引入两个指针,front指向队头元素,rear指向队尾元,让队头指针和队尾指针随着元素的变化而移动。这样我们入队和出队操作都是O(1)。 问题 :rear指针到了表尾就不能后移了,而且出队front一直后移,前面的空间就浪费了。 优化二 :当队头或队尾指针到达尾部时,如需后移可重新指向表头,就相当于是把线性表首尾相连,变成一个环,指针从尾到头有一个周期性,也就是数线性表长度,指针+1对线性表长度取余就可以完成指针从头到尾的跳跃,这样就解决了空间浪费的问题。 问题 :但是又有新的问题,我们判断队列满和队列空的条件都是(rear+1)%n==front,这里n是线性表的长度,这就没法做正确的判断了。 优化三

数组指针和指针数组

戏子无情 提交于 2019-12-17 21:37:58
目录 数组指针 第一个例子: 第二个例子: 指针数组 数组指针 如何记忆:这是一个指针,数组是指针的修饰词,指针为主,数组为辅。所以指针表达为(*ptr),数组表达式为:int [] 结合在一起就是int (*ptr) [n] 数组指针表示指向一个整型的一维数组,这个一维数组的长度是n。 第一个例子: 看下图结果: ptr和ptr+1 之间字节为2*16-C = 20,20正好是n*sizeof(int);说明 执行p+1时,p要跨过n个整型数据的长度 。 以此表明数组指针又称为行指针 #include<iostream> using namespace std; int main(){ int a[5] = {1,2,3,4,5}; int (*ptr)[5] =&a; cout<<"ptr:"<<ptr<<" "<<"a:"<<a<<endl; cout<<"ptr+1:"<<ptr+1<<" "<<"a+1:"<<a+1<<endl; system("pause"); return 0; } 结果如下: a和&a指向的是同一块地址,但他们+1后的效果不同,a+1是一个元素的内存大小(增加4),而&a+1增加的是整个数组的内存大小(n*sizeof(int))。既a和&a的指向和&a[0]是相同的,但性质不同! 总结: 其实a和 &a结果都是数组的首地址,但他们的类型是不一样。

指针深入

女生的网名这么多〃 提交于 2019-12-17 18:28:16
指针的数组 本质是数组,数组中的每个元素都是指针 int p[10]; 占用的内存空间大小 = 指针大小 数组长度 = 8 * 10 = 80 p[0]~~~~p[9] 都是 int * char pstr[8];//8 8 = 64 0 '\0' NULL int main(int argc, const char * argv[]) { char pstr[5]={NULL};//把指针数组中的每个指针变量都初始化为NULL for (int i=0; i<5; i++) { pstr[i]=(char )malloc(1000); if (!pstr[i]) { return -1; } scanf("%s", pstr[i]); } for (int i=0; i<5; i++) { printf("%s\n", pstr[i]);//%s占位符,对应跟字符串首地址 } return 0; } char str[5][100] str[0] --> char char str[0][100] ---> char [100] ---> char int main(int argc,const char argv[]) { //char pstr[5]={"hello","world","qian","feng","welcome"}; char *pstr[5]={NULL}

c++中new和delete的使用方法

独自空忆成欢 提交于 2019-12-17 06:05:10
http://www.jb51.net/article/49537.htm 对于计算机程序设计而言,变量和对象在内存中的分配都是编译器在编译程序时安排好的,这带来了极大的不便,如数组必须大开小用,指针必须指向一个已经存在的变量或对象。对于不能确定需要占用多少内存的情况,动态内存分配解决了这个问题。 new和delete运算符是用于动态分配和撤销内存的运算符。 一、new用法 1.开辟单变量地址空间 使用new运算符时必须已知数据类型,new运算符会向系统堆区申请足够的存储空间,如果申请成功,就返回该内存块的首地址,如果申请不成功,则返回零值。 new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有标识符名。 一般使用格式: 格式1:指针变量名=new 类型标识符; 格式2:指针变量名=new 类型标识符(初始值); 格式3:指针变量名=new 类型标识符 [内存单元个数]; 说明:格式1和格式2都是申请分配某一数据类型所占字节数的内存空间;但是格式2在内存分配成功后,同时将一初值存放到该内存单元中;而格式3可同时分配若干个内存单元,相当于形成一个动态数组。例如: 1)new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址。int *a = new int