C语言数组指针加1的问题

news/2024/11/9 9:20:43/

目录

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\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);

}

输出结果如图:


http://www.ppmy.cn/news/461843.html

相关文章

指针+1,怎么加?

指针1 指针&#xff0b;1&#xff0c;是加一个单元格还是加一个字节呢&#xff0c; 先看一个程序&#xff1a; #include <stdio.h> int main() {int arr[] {1,2,3,4,5,6,7,8,9,10};int *p arr;p;//p p 1*p 10;p;*p 20;printf("%d,%d\n",arr[0],arr[1])…

指针加1

日常生活中我们常用的计算是加减乘除&#xff0c;那么对于指针来说&#xff0c;它却只有加减运算 首先我们先讨论指针加一是怎么加的 可以参考下列代码 int main() {int arr[10] {0,1,2,3,4,5,6,7,8,9};int *p arr;//将数组arr[0]的地址赋给指针变量pprintf("%d\n"…

6-1

今天是儿童节&#xff0c;本来打算晚上去参加一个朋友聚会的&#xff0c;结果身体不舒服&#xff0c;就没去&#xff0c;好遗憾 1.继续联调通知GM的功能 2.要细心&#xff0c;耐心&#xff0c;遇到问题不要慌&#xff0c;耐心查找问题&#xff0c;出了问题很正常。 业务熟悉…

1-6

#include <stdio.h> int main() { int a100 ; float b3.14f ; char cC ; printf("a%d\n",a); printf("b%.2f\n",b); printf("c%c\n",c); return 0 ; }

【2023-1-6】沟通加风险 每日5题

沟通加风险 每日5题 1.项目经理发现一名新的团队资源不具备完成分配给其角色所需的技能。项目经理应该做什么? The project manager finds that a new team resource does not have the skills required to complete the job assigned to him. What should the project manag…

【66】加一

题目 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&#xff0c; 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外&#xff0c;这个整数不会以零开头。 我的解题 把digits先转换成str&#xff0c…

从零开始搭建群众权益平台(八)

部署过程将涉及多个步骤&#xff0c;具体取决于你选择的部署方法和目标平台。这里将以部署到云服务器为例&#xff0c;提供一个基本的流程&#xff1a; 1. 获取服务器&#xff1a; 首先&#xff0c;你需要一个服务器。你可以选择各种云服务提供商&#xff0c;如AWS、Google C…

1加7 pro (oneplus7 pro) drivedroid测试

网上盛传UFS 3.0如何快法&#xff08;androbench软件测试结果&#xff09;&#xff0c;顺序读取1000MB/s&#xff0c;顺序写入600MB/s&#xff0c;但涉及到drivedroid这个软件&#xff0c;我们要测试的是USB与电脑连接后的传输速度。 先说明一下&#xff0c;我的手机型号是GM1…