| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C语言数组指针加1的问题 -> 正文阅读 |
|
[C++知识库]C语言数组指针加1的问题 |
目录 指向数组的指针存储的是连续的内存地址,而内存地址的最小编址单位是1字节,如果存储的数据本身移动几个字节,则内存地址也相应地移动几个字节。而数组指针的加1移动几个字节,取决于所指向的数组类型,这部分是由C/C++的编译器实现去处理的。下面具几个例子说明(下面的例子在MSVC的X64平台,指针本身占8个字节): 1. 用C++语言测试(1) 指向1字节的数组指针: void TestPointerSize() { ??? char data[] = {1,2,3,4,5,6,7,8,9,10}; ??? char* ptr = data; ??? printf("ptr size=%d,data=%I64d\n",sizeof(ptr),data); ??? for(int i=0;i<10;i++) ??? { ??????? printf("data[%d]=%d,ptr=%I64d\n",i,*ptr,ptr);?? ??????? ptr = ptr + 1; ??? } } 输出如图:
从图中可以看到,指针本身的大小占8个字节,数组名是数组的首地址,常量指针。但注意,sizeof(data)是计算整个数组的存储大小,而不是首地址的大小。指针每次加1,也是加1字节长度,即1个数组元素的大小。 (2) 指向2字节的数组指针: void TestPointerSize() { ??? short data[] = {1,2,3,4,5,6,7,8,9,10}; ??? short* ptr = data; ??? int n = sizeof(data); ??? printf("ptr size=%d,data=%I64d\n",sizeof(ptr),data); ??? for(int i=0;i<10;i++) ??? { ??????? printf("data[%d]=%d,ptr=%I64d\n",i,*ptr,ptr);?? ??????? ptr = ptr + 1; ??? } } 输出如图:
可以看到,指针每次加1,是加2字节长度,即1个数组元素的大小。 (3) 指向4字节的数组指针: void TestPointerSize() { ??? int data[] = {1,2,3,4,5,6,7,8,9,10}; ??? int* ptr = data; ??? int n = sizeof(data); ??? printf("ptr size=%d,data=%I64d\n",sizeof(ptr),data); ??? for(int i=0;i<10;i++) ??? { ??????? printf("data[%d]=%d,ptr=%I64d\n",i,*ptr,ptr);?? ??????? ptr = ptr + 1; ??? } } 输出如图:
可以看到,指针每次加1,是加4字节长度,即1个数组元素的大小。 (4) 指向8字节的数组指针: void TestPointerSize() { ??? __int64 data[] = {1,2,3,4,5,6,7,8,9,10}; ??? __int64* ptr = data; ??? int n = sizeof(data); ??? printf("ptr size=%I64d,data=%I64d\n",sizeof(ptr),data); ??? for(int i=0;i<10;i++) ??? { ??????? printf("data[%d]=%I64d,ptr=%I64d\n",i,*ptr,ptr);??? ??????? ptr = ptr + 1; ??? } } 输出如图:
可以看到,指针每次加1,是加8字节长度,即1个数组元素的大小。 2. 用汇编语言测试(MASM环境)(1) 指向1字节的数组指针: 汇编声明一个数组: .const ?? data_ byte 1,2,3,4,5,6,7,8,9,10 C++下声明一个访问数组元素的函数,并用汇编实现 extern "C" int GetArrayItem(int i,char* ptr); 汇编语言实现: ??? .code GetArrayItem proc ??? ; Make sure 'i' is valid ??? cmp ecx,0 ??? jl InvalidIndex ;jump if i < 0 ??? cmp ecx,[NumFibVals_] ??? jge InvalidIndex ;jump if i >= NumFibVals_ ??? ; Sign extend i for use in address calculations ??? ;mov rax,offset data_ ;get ??? lea rbx,data_? ;取得数组的偏移地址,我们可以理解为取得数组的地址,也可换成offset伪指令 ??? xor rax,rax ??? mov eax,ecx ??? imul eax,1?? ;i的值乘以数据的大小,这里是1字节 ??? movsxd rax,eax? ;符号扩展到64位 ??? add rbx,rax ;得到数组的偏移地址 ??? mov eax,[rbx] ;取得偏移地址指向的内存存储的值 ??? mov [rdx],eax? ;将值复制到外部传入的指针所指示的内存地址 ??? mov eax,1 ;set success return code ??? ret ??? InvalidIndex: ??? xor eax,eax ;set error return code ??? ret GetArrayItem endp end 调用代码: void TestPointerSize() { ??? char* ptr = (char*)malloc(sizeof(char)); ??? for(int i=0;i<10;i++) ??? { ??????? GetArrayItem(i,ptr); ??????? printf("data[%d]=%d\n",i,*ptr); ??? } free(ptr); } 输出结果如图: ? (2) 指向2字节的数组指针: 汇编声明一个数组: .const ??? data_ word 2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 汇编访问代码改一句: imul rbx,2?? ;i的值乘以数据的大小,现在这里是2字节 改调用函数: extern "C" int GetArrayItem(int i,short* ptr); 调用代码: void TestPointerSize() { ??? short* ptr = (short*)malloc(sizeof(short)); ??? for(int i=0;i<10;i++) ??? { ??????? GetArrayItem(i,ptr); ??????? printf("data[%d]=%d\n",i,*ptr); ??? } ?? free(ptr); } 输出结果如图: (3) 指向4字节的数组指针: 汇编声明一个数组: .const ??? data_ dword 3001,3002,3003,3004,3005,3006,3007,3008,3009,3010 汇编访问代码改一句: imul rbx,4 ??;i的值乘以数据的大小,现在这里是4字节 改调用函数: extern "C" int GetArrayItem(int i,int* ptr); 调用代码: void TestPointerSize() { ??? int* ptr = (int *)malloc(sizeof(int)); ??? for(int i=0;i<10;i++) ??? { ??????? GetArrayItem(i,ptr); ??????? printf("data[%d]=%d\n",i,*ptr); ??? } ?? free(ptr); } 输出结果如图: (4) 指向8字节的数组指针: 汇编声明一个数组: .const ??? data_ qword 8001,8002,8003,8004,8005,8006,8007,8008,8009,8010 汇编访问代码: GetArrayItem proc ??? ; Make sure 'i' is valid ??? cmp ecx,0 ??? jl InvalidIndex ;jump if i < 0 ??? cmp ecx,[NumFibVals_] ??? jge InvalidIndex ;jump if i >= NumFibVals_ ??? ; Sign extend i for use in address calculations ??? ;mov rax,offset data_ ;get ??? lea rbx,data_? ;取得数组的偏移地址,我们可以理解为取得数组的地址,也可换成offset伪指令 ??? xor rax,rax ??? mov eax,ecx ??? imul eax,8? ;i的值乘以数据的大小,这里是8字节 ??? movsxd rax,eax ;符号扩展到64位 ??? add rbx,rax ;得到数组的偏移地址 ??? mov rax,[rbx] ;取得偏移地址指向的内存存储的值 ??? mov [rdx],rax? ;将值复制到外部传入的指针所指示的内存地址 ??? mov eax,1 ;set success return code ??? ret ??? InvalidIndex: ??? xor eax,eax ;set error return code ??? ret GetArrayItem endp 改调用函数: extern "C" int GetArrayItem(int i,__int64* ptr); 调用代码: void TestPointerSize() { ??? __int64* ptr = (__int64*)malloc(sizeof(__int64)); ??? for(int i=0;i<10;i++) ??? { ??????? GetArrayItem(i,ptr); ??????? printf("data[%d]=%d\n",i,*ptr); ??? } ?? free(ptr); } 输出结果如图: |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 22:24:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |