指针与数组

Posted luoxuw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针与数组相关的知识,希望对你有一定的参考价值。

#include <stdio.h>
#include <limits.h>
//操作数组的本质是操作指针,因为指针太麻烦,不便于理解,所以才抽象出简单的指针,也是就是数组,a[i]是 *(a+i)的简写
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main1()
    int a[5] =1,2,3,4,5;
    // a=0x1233333; a是常量,不能为左值
    printf("%x,%d,%x\n",a,*a,*(a+1)); //61feac,1,2
    //数组名a代表数组的首地址,,*a就是按照int类型往后取出4个字节的数据,按照int类型来解析 %d来解析
    //数组名a代表数组的首地址,a+1要按照a的类型给a地址加1,也就是加int类型的四个字节,a+1=&a[1]
    for (int i = 0; i < 5; ++i) 
        printf("%x,%x",&a[i],a+i);  //&a[i]等价于a+i,a+i就是从首地址a开始,每次往后移动i个sizeof(int)个字节数的地址
        printf("   %d,%d\n",a[i],*(a+i));  // a[i]本质等价于 *(a+i)  然后再从上面的首地址读取int类型的数据
    
    //用指针循环方式遍历数组,数组名是一个常量地址   a=a 是错误的,常量无法赋值
    int *px =a; //a常量地址赋值给指针变量
    for (; px < a+5 ; ++px)    //指针每次自增,往前移动4个字节,也就是一个数组元素,指针自增不要越界,只有在数组内才有意义
        printf("%d  ",*px);   //指针方式循环,px的值会改变
    
    printf("\nfour ways of presenting array are the same:\n");
    int *p =a;
    for (int i = 0; i < 5; ++i) 
        printf("%d,%x  ",a[i],&a[i]);
        printf("%d,%x  ",*(a+i),a+i);
        printf("%d,%x  ",p[i],&p[i]);   //i的方式循环p的值不变
        printf("%d,%x  \n",*(p+i),p+i);
        /*four ways of presenting array are the same:
        1,61fea4  1,61fea4  1,61fea4  1,61fea4
        2,61fea8  2,61fea8  2,61fea8  2,61fea8
        3,61feac  3,61feac  3,61feac  3,61feac
        4,61feb0  4,61feb0  4,61feb0  4,61feb0
        5,61feb4  5,61feb4  5,61feb4  5,61feb4
                 * */
    
    printf("\n\n");
    //指针比较
    int num=SHRT_MAX +100;
    short *p1 =#
    double *p2 =#
    if(p1==p2)    //指针可以比较地址,是否相等,地址相等并不意味着其所指向的值相等,还要看他们如何按其类型解析
        printf("指针相等\n");
        printf("%d!=%d",*p1,*p2);  //-32669!=32867
    

    // 优先级 *p++  等价于*(p++)  ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++]
    //*(++p)  先自增++p,后引用*(p=p+1),等价于 a[++i]
    //


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main2()
    int a[5] =1,2,3,4,5;
    int *p =a;
    printf("%x\n",p);   //61feb8
    printf("%d,%x\n",*p++,p );  // 1,61febc   优先级 *p++  等价于*(p++)  ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++]
   // printf("%d,%x\n",(*p)++,p );// 1,61feb8    先取*p,再引用1,后再+1, (*p)++=2,p没有变
    //printf("%d,%x\n",*++p,p );//2,61febc 等价于 *(++p)  先自增++p,即&a[1],后引用*(p=p+1),等价于 a[++i]  = a[2]
    int *p1 =&a[1];
    int *p2 =&a[3];
    printf("%d\n",p1-p2); // -2    p1-p2 <0   p1 < p2  p1的下标小于p2的下标
    //指针相减多用于同一块内存,如数组或动态申请的内存,结果等于:地址差/sizeof(类型)


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main3()
    int *pInt;
    double *pDouble;
    printf("%d,%d,%d,%d", sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble)); //4,8,4,4
    //sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble)
    //      4               8               4               4
    //     *pInt        *pDouble            pInt        pDouble
    //   int类型数据    double类型数据      int类型指针   double类型指针,指针大小固定为4个字节


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//指向数组的指针和指向元素的指针  ????
void main4()
    int a[5] =1,2,3,4,5;
    printf("%x,%x\n",a,&a);  //61feb4,61feb4  a和&a的地址一样,但是他们指向的类型不一样  在a和&a前面加*,即是他们所指向的类型
    //printf("%d,%d\n", sizeof(a), sizeof(&a));  //20,4  a指向数组首地址,&a是a的地址,这个打印无意义,不用研究
    printf("%d,%d\n", sizeof(*a), sizeof(*(&a)));  //4,20   *a是a指向数组的第一个元素,占4个字节,*(&a)是&a指向整个数组,是20个字节
    int *p = a; //指向元素的指针  a=&a[0]
    int (*pa)[5] = &a; //指向有5个元素数组的指针.
    // 括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。
    // [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针

    //printf("%d,%d\n", sizeof(p), sizeof(pa));  //4,4       指针地址固定4个字节
    //printf("%d,%d\n", sizeof(p), sizeof(&pa));  //4,4   指针地址固定4个字节
    printf("%d,%d\n", sizeof(*p), sizeof(*pa));  //4,20   *p指向元素, *pa指向数组
    //*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,
    // 因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,
    // 在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//指针引用多为数组
void main()
    int a[3][4]=1,2,3,4,
                 5,6,7,8,
                 9,11,12;
    printf("%p,%p,%p\n",a,&a,*a); //打印三者的地址0061FEA0,0061FEA0,0061FEA0  地址一样
    printf("%d,%d,%d\n", sizeof(*a), sizeof(*&a), sizeof(**a)); //打印三者所指向的类型大小 16,48,4
    // a指向二维数组的行元素大小的指针 16 =4 *4
    // &a指向二维数组大小的指针 48 = 12 *4
    // a指向二维数组的单个元素大小的指针 4
    //打印二维数组
    for (int i = 0; i < 3; ++i) 
        for (int j = 0; j < 4; ++j) 
            printf("%d  %p, ",a[i][j],&a[i][j]);
        
        printf("\n");
    
    printf("%d,%d\n", sizeof(*a), sizeof(**a)); //16 4 a是行指针 *a是列指针  *a=*(a+0)=a[0]  a[i]是一个列指针,&a[i]代表行指针
    printf("%p,%p,%p \n",a,a+1,a+2);
    //a,a+1,a+2分别代表二维数组第一,二,三行的首地址,a是行指针
    printf("%p,%p,%p  \n",*a,*a+1,*a+2);
    //*a,*a+1,*a+2分别代表二维数组第一行第一、二、三列元素的地址 *a是第一行首列指针  *取列
    printf("%p,%p,%p  \n",*(a+1),*(a+1)+1,*(a+2));
    printf("%p,%p,%p  \n",a[1],a[1]+1,a[3]);
    //*(a+1),*(a+1)+1  分别指向第二行第一列和第二行第二列元素的指针   <=> a[1]
    //*(a+2) 指向第三行第一列元素的指针  <=> a[3]
    // a[i]是一个列指针,第i行第一列的地址;&a[i]代表行指针,第i行的首地址
    //结论: a[i][j] = *(*(a+i)+j)   &a[i][j] = *(a+i)+j
/*
    &a[i]== a+i == p+i  &a[i]代表行指针,第i行的首地址
    a[i] == p[i] == *(a+i) == *(p+i)   a[i]是一个列指针,第i行第一列的地址;
    &a[i][j] == &p[i][j] == a[i]+j == p[i]+j == *(a+i)+j == *(p+i)+j
    a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)
*/


 

以上是关于指针与数组的主要内容,如果未能解决你的问题,请参考以下文章

指针数组与数组指针详解

数组指针与指针数组

指针数组与数组指针

C语言 指针数组与数组指针

指针数组与二级指针问题

C语言指针指向一维数组与二维数组?