C语言数组指针加1的问题 目录 1. 用C++语言测试 2. 用汇编语言测试(MASM环境) 指向数组的指针存储的是连续的内存地址,而内存地址的最小编址单位是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 ”,sizeof(ptr),data); for(int i=0;i<10;i++) { printf(“data[%d]=%d,ptr=%I64d ”,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 ”,sizeof(ptr),data); for(int i=0;i<10;i++) { printf(“data[%d]=%d,ptr=%I64d ”,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 ”,sizeof(ptr),data); for(int i=0;i<10;i++) { printf(“data[%d]=%d,ptr=%I64d ”,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 ”,sizeof(ptr),data); for(int i=0;i<10;i++) { printf(“data[%d]=%I64d,ptr=%I64d ”,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 ”,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 ”,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 ”,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 ”,i,*ptr); } free(ptr); } 输出结果如图:
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/38168.html