浅谈C/C++中指针和数组的不同

所属分类: 软件编程 / C 语言 阅读数: 128
收藏 0 赞 0 分享

这边先简单介绍一下内存分区。

内存按照用途划分为五个区:

1.栈区:由系统控制分配和回收。

例如定义变量 int x = 0; int *p = NULL; 变量所占的内存都是分配在栈区的。

2.堆区:由程序员管理。

在C语言中由 malloc 申请的内存,或者在C++中,用 new 申请的内存,是在堆区中申请的。用完之后需要程序员自己回收,否则会造成内存泄漏。

3.全局区:存储全局变量及静态变量

4.常量区:存储常量。

5.代码区:存储编译之后的二进制代码。

数组和指针具有很大的相似性,实际上,数组也是一种指针,一种有点特别的指针。
例如,可以这样申请包含10个 int 型数据的数组

//方式1
int arr[10]; //栈区
//方式2
int *ptr = new int[10]; //堆区

我们也常常在定义一个函数的时候使用指针,而传入实参(argument)的时候使用数组(甚至函数的声明和定义可以用指针和数组混搭)。例如:

void func(int *ptr, int n) {
 //statements
}

int main(void) {
 int arr[10];
 ...
 func(arr, 10);
 return 0;
}

数组名代表着一个地址,是其所占内存单元的首地址。在上例中,arr 和 &arr[0] 是相同的。

数组名表示一个地址,这一点和指针一样。不一样的地方在于数组名是一个固定的地址,数组是存放在栈区的,其地址不能改变,也即是一个 const 。
在用一个指针指向数组的时候,可以有几种形式。

int arrInt[10];
/*
ptr1 和 arrInt 的值是一样的,都是同一块内存空间的首地址。
这种形式规定了 ptr1 指向了一个包含10个元素的整形数组,书写麻烦,同时也限制了指针,因此很少用。
*/
int (*ptr1)[10] = &arrInt;
/*
这种形式就是我们比较熟悉和喜闻乐见的了。
在前面一块代码中,在实参中传入数组名,实际上做了这样一件事情:
int *ptr = arrInt; 形式参数是一个指向了 arrInt 的指针。
重点要解释的地方在下一块代码中说明~~~
*/
int *ptr2 = arrInt;

在C++中,有一种引用类型,相当于给变量取了个别名,在传递参数的时候就不会拷贝参数,提高了效率,减少了内存开销。
显而易见,在传递数组参数的时候,可以使用数组的引用。
数组的引用也有不同的方式:

int arrInt[10];
//和指向数组的指针的第一种定义方式类似
int (&ref1)[10] = arrInt;
//这样写怎么样?
int *&ref2 = arrInt;
/*
编译器会报错:
invalid initialization of non-const reference of type 'int*&' from an rvalue of type 'int*'.
原因在于,在栈区中的数组 arrInt 由系统控制,它的地址不能改变。
如果上面的代码可以通过,就意味着可以通过 ref2 指向其他的地址,从而修改 arrInt 的内存地址,这是不允许的,所以编译不通过。
*/
/*
可以这样做。
ref3 是一个引用,并且是一个常量的引用,引用的是一个 int* 。
由于 ref3 是一个常量引用,它的值不允许被修改,因此 ref3 就能够引用 arrInt。
*/
int * const &ref3 = arrInt;

啰啰嗦嗦讲了这么多,其实就一句话——
在栈区中的数组是一种不能改变地址的指针,或者说是一种 const 指针。
o(╯╰)o
(再多一句~~~)
而在堆区中动态申请内存的数组,也就是我们平时在用的指针。

以上就是浅谈C/C++中指针和数组的不同的详细内容,更多关于c/c++ 指针和数组的资料请关注脚本之家其它相关文章!

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多