首页 > 其他分享 >精通c语言中的指针-数组

精通c语言中的指针-数组

时间:2023-06-21 13:22:49浏览次数:32  
标签:精通 code int px arr ara 数组 类型 指针

一维数组:int ara[3]={1,2,3};

printf("%d\n",ara):

printf("%d\n",&ara):

打印之后,发现ara和&ara两个值是一样的,为什么?

按照我们学习的理解,&ara是取ara的地址,一个是地址,一个是值,不应该一样,那为什么打印出来会是一样的?

 从汇编的角度可以解释这个问题:

  printf("%d\n",ara):

  printf("%d\n",&ara):

        会发现取得值都是lea   eax,[ebp-4],说明在堆栈中就没有为ara这个变量分配空间(如果分配空间了,&ara和ara这两个值肯定不一样)

因此,数组名这个变量和普通的变量不一样,普通的局部变量如果定义之后,函数调用的时候,会在堆栈,一般会是[ebp-xx]的位置为这个变量分配一个空间

而数组名,则是直接使用ebp-xx这个值的,这样从反汇编的角度就解释了,为什么这2个值是一样的。

        CPU的世界里,只认识0和1,虽然这个值是一样的,但是这个2个值的类型是不一样的,可以赋值给ara=4,&ara=5,编译器会报错,给出我们答案。

       ara 是int[3]类型                                                                        数组第一个值的地址。

       &ara是int (*)[3]类型,指针数组,后边会解释这种类型。         把数组当成一个整体,整个数组的地址。

        就像前边学的进制一样,0xFF,当做有符号数就是-1,无符号数就是255.但是CPU可不管你是多少,就是一堆0和1,只有使用的程序员才关心类型,同一个值,不同的类型。

       ara + N是多少呢,可以用前边学的指针解释吗?

       可以, ara是数组第一个值的地址,当做short* ara[0]

       ara + N = ara + N*(short宽度)

 二维数组:

int arr[3][5]={

    {1,2,3,4},

    {5,6,7,8},

    {9,10,11,12}

};

arr ,&arr, *arr  这三个值都一样,理解为整体和局部的关系:

整体:

&arr是数组指针, int (*)[3][5]类型,也是第一个元素的地址(把数组当成一个整体看待,这个地址就是这个整体的地址)。

&arr+N = arr + N*3*5*int宽度

&arr-N = arr - N*3*5*int宽度

局部1:

*arr    宽度为:int的宽度×(第二维数字,5),值为指向数组中第一组数组的地址,第一组数据是{1,2,3,4},这个的地址。

*arr    是int[5]类型

*arr + N = arr + N*(int宽度)

*arr - N = arr - N*(int宽度)

arr是int [3][5]类型,宽度是3*5*4=60,值为指向第一个元素的地址

arr + N = arr + N*(第二维数字,5)*(int宽度)

arr - N = arr - N*(第二维数字,5)*(int宽度)

 多维数组的理解实例:

short code[]={

        0x9e,0x0a,0xc1,0x75,0x82,0xaad9,0xaa,0x2b,0x76,0x39,     //1*20

        0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,      //2*20

        0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,      //3*

        0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,      //4*20

        0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,      //5

        0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,      //6

        0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,      //7*20

        0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,      //8*20

        0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,      //9*20

        0xeed0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0, //10*20

        0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,

        0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,

        0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,      //13*20

        0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,

        0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,      //15*20=300

        0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,      //16*20=320

        0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,      //8400e0

        0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,

        0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,

        0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0,      //20*20

        0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,

        0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,

        0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,

        0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,

        0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,

        0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,

        0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,

        0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,

        0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,

        0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0,

        0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,

        0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,

        0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,

        0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,

        0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,

        0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,

        0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,

        0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,

        0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,

        0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0       //40

};

    unsigned char (*p1)[3];

    unsigned short (*p2)[7];

    int (*p3)[9];

 

    p1 = (unsigned char (*)[3])code;

 

    p2 = (unsigned short (*)[7])code;

 

    p3 = (int (*)[9])code;

 

    printf("%x,%x\n",code[1],code[5]);

 

    printf("%x,%x\n",*(*(p1)+10),code[5]);//p1+10=0x00d9

    printf("%x,%x\n",*(*(p1+5)+9),code[12]);//p1 + 3*5*1+9=24,2a

   

    printf("%x,%x\n",*(*p2+5),code[5]);//p2+5*2,0xd9

    printf("%x,%x\n",*(*(p2+5)+7),code[42]);//p2+5*7*2+7*2=84,0x74

   

    printf("%x,%x\n",*(*p3+3),code[6]);//p3+12=0x2b00aa

    printf("%x,%x\n",*(*(p3+7)+3),code[132]);//p3+7*9*4+3*4=264,8e0045

 

 

    int (*px)[4][3][5];

    unsigned char (*py)[3][5][6];

    px =(int (*)[4][3][5])code;

    py = (unsigned char (*)[3][5][6])code;

    printf("%x,%x\n",*(*(*(*(px+1)+1)+1)+1),code[162]);

    printf("%x,%x\n",*(*(*(*(px+1)+1)+1)+1),code[162]);//px+1*4*3*5*4 + 1*3*5*4 + 1*5*4 + 1*4 =324,8400e0

    printf("%x,%x\n",*(*(*(*(py+2)+3)+4)+6),code[150]);//py+2*3*5*6*1 + 3*5*6*1 + 4*6*1 + 6*1=300,aa

 

    类型N (*px)[i][j][k]

    *(*(*(*(px+X)+Y)+Z)+M)=p的地址+p去掉*号的类型×X×类型N + Y×(*p的类型)×类型N + Z*(**p的类型)× 类型N + M*类型N  = p的地址 + X×i×j×k×类型N + Y×j×k×类型N + Z×k×类型N+ M*类型N 。注意取出来的值是类型N。

   理解方法:

       px是类型N (*)[i][j][k]类型,是指向类型N [i][j][k]数组的指针,px+X,就是加上去掉*号的类型乘以X,去掉*号的类型是类型N [i][j][k],因此是加上px + X*i*j*k*类型N

    *(px + X),取*之后类型就由整个3维数组的地址转换为指向2维数组的地址,就变成了指向(类型N (*)[j][k])的类型,即因此去掉*号之后就是(类型N  [j][k])的数组地址类型,因此*(px + X)+ Y,就是加上Y*j*k*类型N;

    *(*(px + X)+Y) ,取*之后类型之后,就变成了(类型N (*) [k])的类型,即指向(类型N  [k])的数组地址,因此*(*(px + X)+Y)+Z,就是加上z*k*类型N;

    *(*(*(px + X)+Y)+Z) 取*之后,类型就变成了指向数组第一个元素的地址,因此加*(*(*(px + X)+Y)+Z) + M,加的得就是加上M×去掉*号的类型,即M*类型N

       *(*(*(*(px + X)+Y)+Z) + M),再取*号,就是取出这个地址的值。

       可以理解为由整体的三维数组到数组中变量的地址转换,每次*号一次就是一次类型变化。

 

标签:精通,code,int,px,arr,ara,数组,类型,指针
From: https://www.cnblogs.com/gusseMe/p/17495644.html

相关文章

  • 各种语言中对指针的叫法
    如果没有指针,就无法构造正统的数据结构,因此,比较成熟的、正统的编程语言,必定会存在指针3。3以前,FORTRAN、COBOL和BASIC中都没有指针,但是在fortran90、VisualBasic等升级版中,正式引入了指针功能。咦?我怎么听说Java就没有指针呢……我可以负责任地告诉你,这是个谣言。......
  • Const 关键字 与指针
    Const关键字与指针发表于2007年04月29日由不及格的程序员-八神星期一天气:晴 使用指针会涉及到两个对象一个是指针本身,另一个是它指向的对象.将指针声明为const就使对象为常量而不是指针为常量;例如:constchar*p="asdf";//指向常量的指针p[2]=‘d’; /......
  • js 数组 map方法
    一、map的第一种使用场景需求:我们想得到对象数组中指定的两组或多组key和value值。如下图:下面是一段JSON数据结构{"code":0,"msg":null,"data":[{"processDetailId":1381753495314433,"processId":138175349......
  • 精通c语言中的指针(精通c指针1)
    之前学c语言的时候,指针这一章学的半吊子,似是而非,最近经过学习,对指针有个更加深刻的理解。如果之前学过c指针,并且可以使用指针随心所欲操作内存中的任何数据,那么说明指针学好了,否则就是半吊子。如果之前学过指针,那最好忘记之前学过的所有概念,把指针当做一种新的类型来学习。这种......
  • 【算法】编写一个函数,返回数字数组的“峰值”(或局部最大值)的位置和值。
    编写一个函数,返回数字数组的“峰值”(或局部最大值)的位置和值。例如,数组arr=[0,1,2,5,1,0]在位置3处具有值为5的峰值(因为arr[3]等于5)。输出将以Dictionary<string,List<int>的形式返回,其中包含两个键值对:“pos”和“peaks”。如果给定的数组中没有峰值,只需返回{“pos”=>newList<int>(),“pea......
  • C++ 智能指针
    unique_ptrunique_ptr为了避免重复释放(doublefree)问题出现,进行拷贝(删除了拷贝构造函数)这样的特性带来的问题是无法进行参数传递(因为参数传递需要拷贝构造函数),有两种解决方法想要解决这个问题,首先需要理解为什么unique_ptr会禁止拷贝,对一个指针进行拷贝......
  • C语言-指针进阶详解(万字解析)
    前言本篇内容主要针对指针的进阶详解,如果不懂指针的含义要自行去看书看视频了解一下。指针指针是个特殊的变量,其功能就是来存放地址,地址唯一标识一块内存空间。指针的大小有两种一种是32位操作系统下的4个字节,一种是64位操作系统的8个字节。同时指针是有类型的,不同的类型决定了指针......
  • 将int数组转为Stirng数组输出
    publicclassStr{publicstaticvoidmain(String[]args){//数组int[]arrNum={1,2,3,4,5,6};Stringresult1=arrayTostring(arrNum);System.out.println(result1);}publicstaticStringarrayTostring(int[]......
  • 2023-06-20:给定一个长度为N的数组arr,arr[i]表示宝石的价值 你在某天遇到X价值的宝石, X
    2023-06-20:给定一个长度为N的数组arr,arr[i]表示宝石的价值你在某天遇到X价值的宝石,X价值如果是所有剩余宝石价值中的最小值,你会将该宝石送人X价值如果不是所有剩余宝石价值中的最小值,你会将该宝石放到所有宝石的最后返回把宝石都送人需要多少天比如arr=[3,1,4,3,1,2]在第1......
  • 2023-06-20:给定一个长度为N的数组arr,arr[i]表示宝石的价值 你在某天遇到X价值的宝石, X
    2023-06-20:给定一个长度为N的数组arr,arr[i]表示宝石的价值你在某天遇到X价值的宝石,X价值如果是所有剩余宝石价值中的最小值,你会将该宝石送人X价值如果不是所有剩余宝石价值中的最小值,你会将该宝石放到所有宝石的最后返回把宝石都送人需要多少天比如arr=[3,1,4,3,1,2]在第1天,你遇......