指针练习题

此程序在X86环境下运行
由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
    int Num;
    char* pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p;
//假设p 的值为0x000000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
    printf("%d\n",sizeof(struct Test));
    printf("%p\n", p);// 0x000000

    //此时的p为struct Test*类型,+1跳过20个字节
    printf("%p\n", p + 0x1);//0x000014      - 20

    //p为unsigned long类型,长整形,+1
    printf("%p\n", (unsigned long)p + 0x1);//0x000001

    //p为unsigned int*类型,+1跳过四个字节
    printf("%p\n", (unsigned int*)p + 0x1);//0x000004
    return 0;
}

//小端存储,低位在低地址,高位在高地址
//计算机读取的顺序是从低地址到高地址
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    /*
        低            高地址
        0x000002
        01    00    00    00
        0x000006
        02    00    00    00
        03    00    00    00
        04    00    00    00

        所以读取00 00 00 02
        故*ptr2的结果为00 00 00 02
    */
    int* ptr1 = (int*)(&a + 1);
    // a为数组名,代表数组首元素地址,假设为0x000001
    // 则(int)a的值为0x000001
    // (int)a + 1为 0x000002
    // (int*)((int)a + 1)代表0x000002为int*类型
    // 所以*ptr2是从0x000002开始读取int类型长度的数据
    int* ptr2 = (int*)((int)a + 1);
    // 0x02 00 00 00
    printf("%d,%x", ptr1[-1], *ptr2);
    return 0;
}

#include <stdio.h>
int main()
{
    //里面的括号是逗号表达式***********
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    /*
        int *p = a[0]-- int*类型
            ↓
            1    3
            5    0
            0    0
    */
    int* p;
    p = a[0];
    printf("%d", p[0]);//1
    // p[0] --> *(p+0) --> *(a[0] + 0)
    return 0;
}

int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    /*
        -4
        10000000 00000000 00000000 00000100 原码
        11111111 11111111 11111111 11111011 反码
        11111111 11111111 11111111 11111100 补码   -4在内存中的存储形式
        
        一.以%d的形式打印
        C语言会将11111111 11111111 11111111 11111100看成一个有符号数在内存中存储

        二.以%p的形式打印
        C语言会将11111111 11111111 11111111 11111100看成一串地址
        FF FF FF FC

        ----------
    */
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//-4  
    /*
        //第一种理解,公式法
         &p[4][2] - &a[4][2]
         &*(p[4]+2) - &*(a[4]+2)
         p[4]+2 - (a[4]+2)
         p[4]+2-a[4]-2
         p[4]-a[4]
         *(p+4) - *(a+4)
         因为p = a,假设他们的初始地址为0
         因为p是int(*)[4]类型,故p+4走过16个int
         因为a是int(*)[5]类型,故a+4走过20个int
         16-20 = -4
         故&p[4][2] - &a[4][2]之间相差-4个int
        ----
    */
    /*
        printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//-4  
        //第二种理解
        p的类型是int(*)[4],是一个数组的指针,该数组有四个元素,每个元素int类型

        假设p=a,他们的初始地址为0

        p[4]--> *(p+4),其中 p+4 代表跳过4个int(*)[4]类型的大小,也就是跳过16个int的地址
        此时地址从0变为0+16*4=64, 但p+4的类型仍为int(*)[4]类型,
        但*(p+4)为int*类型, 

        p[4][2]--> *(p+4)[2] --> *(*(p+4)+2)
        因为*(p+4)为int*类型,所以*(p+4)+2向后跳过2个int*类型,来到64+2*4=72
        *(p+4)+2仍然为int*类型
        *(*(p+4)+2) 为int类型,表示地址为72,这个int类型元素的数值
        
        &p[4][2] --> &(*(*(p+4)+2)) 
        因为*(*(p+4)+2) 为int类型,所以&(*(*(p+4)+2))为int*类型
        故&p[4][2]为int*类型,地址为72
        ==================================================================================================
        ==================================================================================================
        &a[4][2]

        a为int(*)[5]类型,是指向数组的指针,该数组有五个元素,每个元素为int类型
        a[4] --> *(a+4)  0+4*5*4 = 80 
        a+4是 int(*)[5]类型
        *(a+4)是int*类型

        a[4][2] --> *(*(a+4)+2) 80+4*2=88
        *(a+4)+2是int*类型
        *(*(a+4)+2)是int类型

        &a[4][2] int*类型

        ==================================================================================================
        ==================================================================================================
        (72-88)/4 = -4


        ----------------
    */
    return 0;
}

int main()
{
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int* ptr1 = (int*)(&aa + 1);
    int* ptr2 = (int*)(*(aa + 1));
    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
    return 0;
}

// 假如一个类型是int*类型,该类型+1跳过1个int


int main()
{
    // a[]是一个指针数组,有三个元素,每个元素为char*类型
    // a是数组名,代表首元素地址,首元素为char*类型,故a为char**类型
    // 
    char* a[] = { "work","at","alibaba" };
    char** pa = a;
    pa++;
    printf("%s\n", *pa);//at

    //int a[10];
    //int(*p)[10] = &a;
    数组指针指针
    //int(**p2)[10] = &p;
    return 0;
}
 

int main()
{
    char* c[] = { "ENTER","NEW","POINT","FIRST" };
     /*
        c[]是指针数组,有4个元素,每个元素为char*类型,用来存放char类型的地址
        c数组名,代表数组首元素地址,首元素类型为char*类型,故c为char**类型,用于存放char*类型的地址
        

        cp[]是指针数组,有三个元素,每个元素用来存放char*类型的地址,每个元素的类型为char**
        cp为数组名,代表首元素地址,首元素为char**类型,故cp为char***类型
     */
    char** cp[] = { c + 3,c + 2,c + 1,c };//cpp

    char*** cpp = cp;

    /*
        ++cpp --> cpp+1 
        cpp为char***类型,cpp+1跳过一个char**类型的大小,
        cp[]的每个元素为char**类型,故cpp+1跳到元素c+2,cpp+1存储元素c+2的地址,为char***类型

        *(cpp+1)为char**类型, 因为cpp+1中是c+2的地址,故*(cpp+1)为c+2,类型为char**
         
        c+2  c是char**类型 c+2跳过2个char*来到"POINT"的首地址,也就是P的地址,P的地址为char*类型
        c+2中为P的地址的地址
        *(c+2)为p的地址
        -----------------
    */
    // 先运行++ 在解引用
    printf("%s\n", **++cpp);//POINT

    /*
        此时cpp指向的位置是cp[1] --> c+2(int**类型)      
        ++cpp --> (cpp+1) --> cpp此时指向的是cp[2] --> c+1(int**类型)
        即cpp = (c+1)的地址
        *++cpp = *(c+1的地址) = c+1 = cp[2]
        -- * ++cpp = --cp[2]= c+1-1 = c(int**类型,存储c[]首元素的地址)  注意cp[2]内的值也改了
        *-- * ++cpp = *(c)=数组c[]的首元素 = c[0](char*类型)
        *-- * ++cpp + 3 = c[0] + 3 = c[0]向后跳过3个char
        ------
    */
    printf("%s\n", *-- * ++cpp + 3);//ER


    /*
        此时cpp指向的元素是cp[2];
        cpp[-2] = *(cpp-2),
        cpp-2:cpp向后跳过2个char**类型的元素,此时cpp指向的元素为cp[0]
        *(cpp-2) = c+3
        *cpp[-2] = *(*(cpp-2) ) = *(c+3) 
        c+3 = c[3]的地址
        *(c+3) = c[3]
         
        *cpp[-2] + 3 = c[3] + 3
        -------
    */
    printf("%s\n", *cpp[-2] + 3);//ST

    /*
        此时cpp指向的位置是cp[2]
        cpp[-1] = *(cpp-1)
        cpp-1指向的元素是cp[1]
        *(cpp-1) = cp[1] = c+2
        
         cpp[-1][-1] = *(*(cpp-1)-1) = *(c+2-1) = *(c+1)
         c+1指向的元素为c[1]
         *(c+1) = c[1]
         
         cpp[-1][-1] + 1 = c[1]+1
        -------------
    */
    printf("%s\n", cpp[-1][-1] + 1);//EW
    return 0;
}

int main()
{
    int arr[] = { 1,5,9,22 };
    int* p = arr;
    printf("%d", --*++p + 1);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值