数组的内存模型

1 一维数组的内存模型

一维数组说开了就是一组连续的数值,这组数值存储在一段连续的内存空间之中,只是不一样的是,若是我们不定义数组我们来访问这一连串的数值需要n个变量对应这n个数值或是需要一个指针进行遍历。只是现在我们为这一组值起了个名字而已,以后我们便可以通过这个名字+下标来访问这一组值了。

如我们定义了一个数组:

char a[] = “hello world”;

它的大小为sizeof a = 12(包含一个’/0’)

如果我们不想包含这个’/0’,可以改用下面的方式初始化:

char a[] = {'h','e','l','l','o','w','o','r','l','d'};

这样数组的大小就变成了sizeof a = 10;去掉了一个空格和’/0’;

下面我们用程序探索一下它的内存模型:

#include "stdio.h"

void main()

{

    char a[] = {'h','e','l','l','o','w','o','r','l','d'};

    printf("addr of &a:%#x/n",&a);

    printf("addr of a:%#x/n",a);

    printf("addr of a[0]:%#x/n",&a[0]);

    printf("addr of a[1]:%#x/n",&a[1]);

    printf("addr of &a+1:%#x/n",&a+1);

    printf("addr of a+1:%#x/n",a+1);

}

输出结果为:

 

好的,我们来分析一下结果:

在分析之前我们先去理解一些这几个符号所代表的含义:

&a: -       代表整个数组的地址

a:          代表第一个元素的地址

&a[0]:            代表第一个元素的地址

&a[1]:            代表第二个元素的地址

&a+1:            最末端后一个地址

a+1:               第一个元素的地址

&a[0]+1:        第一个元素的地址

如果你能把这些都理解了,那也就无需分析了。呵呵。。。

好的,我们来看一下它的内存模型吧:

 

2 二维数组

二维数组比一维数组稍复杂了些,它可以理解为数组的数组,即在一维数组里每个元素又是一个数组。

同样我们用一个程序来看一下二维数组的内存模型:

#include "stdio.h"

char a[2][5];

void main()

{

    printf("addr of &a:%#x/n",&a);

    printf("addr of a:%#x/n",a);

    printf("addr of a[0]:%#x/n",&a[0]);

    printf("addr of a[1]:%#x/n",&a[1]);

    printf("addr of &a+1:%#x/n",&a+1);

    printf("addr of a+1:%#x/n",a+1);

    printf("addr of a[0][0]:%#x/n",&a[0][0]);

    printf("addr of a[0][1]:%#x/n",&a[0][1]);

    printf("addr of a[1][0]:%#x/n",&a[1][0]);

}

输出结果:

 

用图来表示内存模型如下:

 

3 三维数组

三维数组更为复杂,在我们编程生活中很少遇得到的。不过我们还是应该了解一下的.

同样程序:

#include "stdio.h"

int apricot[2][3][5];

int (*r)[5] = apricot[0];

int *t = apricot[0][0];

void main()

{

    printf("addr of apricot:%#x/n",apricot);

    printf("addr of r:%#x/n",r);

    printf("addr of t:%#x/n",t);

    printf("addr of ++r:%#x/n",++r);

    printf("addr of ++t:%#x/n",++t);

    printf("addr of apricot+1:%#x/n",apricot+1);

    printf("addr of &apricot+1:%#x/n",&apricot+1);

    printf("addr of apricot[0][0][0]:%#x/n",&apricot[0][0][0]);

    printf("addr of apricot[0][0][1]:%#x/n",&apricot[0][0][1]);

    printf("addr of apricot[1][0][0]:%#x/n",&apricot[1][0][0]);

}

输出结果:

 

由于三位数组比较多,这里就不在画图了,它在内存中的存储仍是顺序存储的。即如:

char  a[2][3][5];这个三位数组.它有两个元素,每个元素又是一个二维数组。存储的时候首先存储第一个二维数组,然后在顺序存储第二个二维数组。

总结:

经过对一位数组,二维数组,三维数组的分析,我们可以总结出一个规律。即当一个地址+1的时候,这个1的含义是根据这个地址的类型来确定的。如:

int a[5];

a代表第一个元素的地址。它的类型为一个元素的地址。故a+1代表a[1].只往后移动了一个元素位置,即sizeof(*a);

&a代表整个数组的地址。所以&a+1.往后移动的长度为:sizeof(a);

&a[1]代表第一个元素的地址。所以&a[1]+1往后移动的长度为:sizeof(a[1]);

:

int a[3][10];

a  代表第一维的地址。所有a+1往后移动的距离为:sizeof(a[0]);:10*sizeof(int)

&a 代表二维数组的地址.所以&a+1往后移动过的距离为:sizeof(a);3*10*sizeof(int);

&a[1]代表第二维的地址。所以&a[1]+1往后移动的距离为:sizeof(a[1])+1:10*sizeof(int).

另外我们总结一下能够遍历数组所需用的指针:

遍历一位数组:

:int a[10];

由于数组中的元素的类型为int,所以我们只需一个int型指针就可以遍历数组了:

int *p = a;

遍历二维数组:

:int a[3][20];

由于我们可以理解为是数组的数组。所以数组元素的类型为数组。所以我们需要一个数组指针来遍历二维数组:

int (*p)[20];

p = a;

现在p为指向含有20个元素的一位数组指针。他可以指向a[0],a[1],a[2].如需要再去遍历各个一位数组中的内容。我们仍需要改变:我们可以按照下面程序中的方法去进行;

#include "stdio.h"

void main()

{

    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};

    int (*p)[3] = a;

    printf("p[0]:%d/n",*p[0]);

    printf("p[1]:%d/n",*p[1]);

    printf("p[2]:%d/n",*p[2]);

    printf("*p+1:%d/n",*(*p));

    printf("*p+1:%d/n",*(*p+1));

    printf("*p+1:%d/n",*(*p+2));

    printf("*p+1:%d/n",*(*(p+1)));

    printf("*p+1:%d/n",*(*(p+1)+1));

    printf("*p+1:%d/n",*(*(p+1)+2));

    printf("*p+1:%d/n",*(*(p+2)));

    printf("*p+1:%d/n",*(*(p+2)+1));

    printf("*p+1:%d/n",*(*(p+2)+2));

}

输出结果:

 

这里我们须明白的是:

p指向的二维数组的首地址,目前它代表二维数组的首地址。

*p 代表第一个一维数组的地址。

*p+1代表第二个一维数组的地址。

……

**p则是代表第一个元素了。

*(*p+1)代表第二个元素.

剩下的也就顺理成章了….

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书重点:探索“对象导向程序所支持的C++对象模型”下的程序行为。对于“对象导向性质之基础实现技术”以及“各种性质背后的隐含利益交换”提供一个清楚的认识。检验由程序变形所带来的效率冲击。提供丰富的程序范例、图片,以及对象导向观念和底层对象模型之间的效率测量。 C++成山似海的书籍堆中,这一本不是婴幼儿奶粉,也不是较大婴儿奶粉,它是成人专用的低脂高钙特殊奶粉。 对于C++底层机制感兴趣的读者,这本书会给你“漫卷诗书喜欲狂”的感觉。 了解C++ Object Model,是学习Component ObjectModel的最短路线。 如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么Inside TheC++ Object Model正适合你。 目录: 本立道生(侯捷 译序) 前言(Stanley B.Lippman) 第0章 导读(译者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple Object Model) 表格驱动对象模型(A Table-driven Object Model) C++对象模型(The C++ Object Model) 对象模型如何影响程序(How the Object Model Effects Programs) 1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态之后(Adding Polymorphism) 第2章 构造函数语意学(The Semantics of constructors) 2.1 Default Constructor的建构操作 “带有Default Constructor”的Member Class Object “带有Default Constructor”的Base Class “带有一个Virual Function”的Class “带有一个virual Base class”的Class 总结 2.2 Copy Constructor的建构操作 Default Memberwise Initialization Bitwise Copy Semantics(位逐次拷贝) 不要Bitwise Copy Semantics! 重新设定的指针Virtual Table 处理Virtual Base Class Subobject 2.3 程序转换语意学(Program Transformation Semantics) 明确的初始化操作(Explicit Initialization) 参数的初始化(Argument Initialization) 返回值的初始化(Return Value Initialization) 在使用者层面做优化(Optimization at the user Level) 在编译器层面做优化(Optimization at the Compiler Level) Copy Constructor:要还是不要? 摘要 2.4 成员们的初始化队伍(Member Initialization List) 第3章 Data语意学(The Semantics of Data) 3.1 Data Member的绑定(The Binding of a Data Member) 3.2 Data Member的布局(Data Member Layout) 3.3 Data Member的存取 Static Data Members Nonstatic Data Member 3.4 “继承”与Data Member 只要继承不要多态(Inheritance without Polymorphism) 加上多态(Adding Polymorphism) 多重继承(Multiple Inheritance) 虚拟继承(Virtual Inheritance) 3.5 对象成员的效率(Object Member Efficiency) 3.6 指向Data Members的指针(Pointer to Data Members) “指向Members的指针”的效率问题 第4章 Function语意学(The Semantics of Function) 4.1 Member的各种调用方式 Nonstatic Member Functions(非静态成员函数) Virtual Member Functions(虚拟成员函数) Static Member Functions(静态成员函数) 4.2 Virtual Member Functions(虚拟成员函数) 多重继承下的Virtual Functions 虚拟继承下的Virtual Functions 4.3 函数的效能 4.4 指向Member Functions的指针(Pointer-to-Member Functions) 支持“指向Virtual Member Functions”之指针 在多重继承之下,指向Member Functions的指针 “指向Member Functions之指针”的效率 4.5 Inline Functions 形式对数(Formal Arguments) 局部变量(Local Variables) 第5章 构造、解构、拷贝 语意学(Semantics of Construction,Destruction,andCopy) 纯虚拟函数的存在(Presence of a Pure Virtual Function) 虚拟规格的存在(Presence of a Virtual Specification) 虚拟规格中const的存在 重新考虑class的声明 5.1 无继承情况下的对象构造 抽象数据类型(Abstract Data Type) 为继承做准备 5.2 继承体系下的对象构造 虚拟继承(Virtual Inheritance) 初始化语意学(The Semantics of the vptr Initialization) 5.3 对象复制语意学(Object Copy Semantics) 5.4 对象的功能(Object Efficiency) 5.5 解构语意学(Semantics of Destruction) 第6章 执行期语意学(Runting Semantics) 6.1 对象的构造和解构(Object Construction and Destruction) 全局对象(Global Objects) 局部静态对象(Local Static Objects) 对象数组(Array of Objects) Default Constructors和数组 6.2 new和delete运算符 针对数组的new语意 Placement Operator new的语意 6.3 临时性对象(Temporary Objects) 临时性对象的迷思(神话、传说) 第7章 站在对象模型的类端(On the Cusp of the Object Model) 7.1 Template Template的“具现”行为(Template Instantiation) Template的错误报告(Error Reporting within a Template) Template中的名称决议方式(Name Resolution within a Template) Member Function的具现行为(Member Function Instantiation) 7.2 异常处理(Exception Handling) Exception Handling快速检阅 对Exception Handling的支持 7.3 执行期类型识别(Runtime Type Identification,RTTI) Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享内存(Shared Memory)
第0章 导读(译者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple Object Model) 表格驱动对象模型(A Table-driven Object Model) C++对象模型(Th e C++ Object Model) 对象模型如何影响程序(How the Object Model Effects Programs) 1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态之后(Adding Polymorphism) 第2章 构造函数语意学(The Semantics of constructors) 2.1 Default Constructor的建构操作 “带有Default Constructor”的Member Class Object “带有Default Constructor”的Base Class “带有一个Virual Function”的Class “带有一个virual Base class”的Class 总结 2.2 Copy Constructor的建构操作 Default Memberwise Initialization Bitwise Copy Semantics(位逐次拷贝) 不要Bitwise Copy Semantics! 重新设定的指针Virtual Table 处理Virtual Base Class Subobject 2.3 程序转换语意学(Program Transformation Semantics) 明确的初始化操作(Explicit Initialization) 参数的初始化(Argument Initialization) 返回值的初始化(Return Value Initialization) 在使用者层面做优化(Optimization at the user Level) 在编译器层面做优化(Optimization at the Compiler Level) Copy Constructor:要还是不要? 摘要 2.4 成员们的初始化队伍(Member Initialization List) 第3章 Data语意学(The Semantics of Data) 3.1 Data Member的绑定(The Binding of a Data Member) 3.2 Data Member的布局(Data Member Layout) 3.3 Data Member的存取 Static Data Members Nonstatic Data Member 3.4 “继承”与Data Member 只要继承不要多态(Inheritance without Polymorphism) 加上多态(Adding Polymorphism) 多重继承(Multiple Inheritance) 虚拟继承(Virtual Inheritance) 3.5 对象成员的效率(Object Member Efficiency) 3.6 指向Data Members的指针(Pointer to Data Members) “指向Members的指针”的效率问题 第4章 Function语意学(The Semantics of Function) 4.1 Member的各种调用方式 Nonstatic Member Functions(非静态成员函数) Virtual Member Functions(虚拟成员函数) Static Member Functions(静态成员函数) 4.2 Virtual Member Functions(虚拟成员函数) 多重继承下的Virtual Functions 虚拟继承下的Virtual Functions 4.3 函数的效能 4.4 指向Member Functions的指针(Pointer-to-Member Functions) 支持“指向Virtual Member Functions”之指针 在多重继承之下,指向Member Functions的指针 “指向Member Functions之指针”的效率 4.5 Inline Functions 形式对数(Formal Arguments) 局部变量(Local Variables) 第5章 构造、解构、拷贝 语意学(Semantics of Construction,Destruction,and Copy) 纯虚拟函数的存在(Presence of a Pure Virtual Function) 虚拟规格的存在(Presence of a Virtual Specification) 虚拟规格中const的存在 重新考虑class的声明 5.1 无继承情况下的对象构造 抽象数据类型(Abstract Data Type) 为继承做准备 5.2 继承体系下的对象构造 虚拟继承(Virtual Inheritance) 初始化语意学(The Semantics of the vptr Initialization) 5.3 对象复制语意学(Object Copy Semantics) 5.4 对象的功能(Object Efficiency) 5.5 解构语意学(Semantics of Destruction) 第6章 执行期语意学(Runting Semantics) 6.1 对象的构造和解构(Object Construction and Destruction) 全局对象(Global Objects) 局部静态对象(Local Static Objects) 对象数组(Array of Objects) Default Constructors和数组 6.2 new和delete运算符 针对数组的new语意 Placement Operator new的语意 6.3 临时性对象(Temporary Objects) 临时性对象的迷思(神话、传说) 第7章 站在对象模型的类端(On the Cusp of the Object Model) 7.1 Template Template的“具现”行为(Template Instantiation) Template的错误报告(Error Reporting within a Template) Template中的名称决议方式(Name Resolution within a Template) Member Function的具现行为(Member Function Instantiation) 7.2 异常处理(Exception Handling) Exception Handling快速检阅 对Exception Handling的支持 7.3 执行期类型识别(Runtime Type Identification,RTTI) Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享内存(Shared Memory)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值