0
点赞
收藏
分享

微信扫一扫

指针进阶一站式练习(内含详细解析)

奔跑的酆 2022-04-23 阅读 47
c语言

#include<stdio.h>

//int main()
//{
//    int a[5] = { 1,2,3,4,5 };
//    int* ptr = (int*)(&a + 1);//数组指针(&a+1)跳过整个数组,5后面的地址,(int*)()强制类型转换
//    printf("%d\n", *(a + 1), *(ptr - 1));//打印结果为2,5
//    //*(ptr-1)是跳过整个数组并-1,是5
//    //*(a+1)为2
//    return 0;
//}


//结构体大小是20,假设p的地址是0x100000
//指针+1,加的实际是多少,取决于指针的类型,结构体指针+1,加的是结构体大小,整形指针+1,加的是4
//字符指针,+1加的是1       整形+1,加的就是1
//struct test    
//{
//    int Num;
//    char* pcName;
//    short sDate;
//    char cha[2];
//    short sBa[4];
//}*p;
//int main()
//{                   
//    printf("%p\n", p + 0x1);//指针名是首元素地址
//    //0x100000+20(结构体类型是20)=0x100014(20转化为16进制为0x100014)
//    printf("%p\n", (unsigned long)p+0x1);//整形+1,加的是4,即0x10001
//    printf("%p\n", (unsigned int*)p + 0x1);//int型,+4,即0x10004
//    return 0;
//}

//ptr被强制转换成int型,+1就是+1    %x是十六进制
//int main()//假设小端存储:为01000000  02000000  03000000 04000000(地位放在低地址,高位放在高地址)
//{
//    int a[4] = { 1,2,3,4 };//int型,如1就需要占4个字节
//    int* ptr1 = (int*)(&a + 1);//&a+1跳过整个数组,(int*)是强制类型转换为int*
//    int* ptr2 = (int*)((int)a + 1);//数组名是首元素地址,a就是地址,(inta)+1就是+1
//    //此时+1就只是+1个字节(int1的四分之一),此时指向的是00000002--->ptr2
//    //(int*)表示将a强制类型转换为int*,并将其存储在ptr2中
//    printf("%x,%x", ptr1[-1], *ptr2);//打印结果为4 20000000
//    //%x是16进制,ptr1[-1]是*(ptr1+(-1)),即向左移动1个整形(int),
//    // 4个字节是一个整型,指向04000000--->ptr1
//    //打印时,倒着打印,为00000004 和20000000
//}


//int main()
//{
//    int a[3][2] = { (0,1),(2,3),(4,5) };//(0,1)逗号表达式,可理解为1,3,5,
//    //二维数组为 1  3(第一行) 5  0(第二行) 0  0(第三行)
//    int* p;
//    p = a[0];//数组名是首元素地址,吧首元素地址传给指针p,p指向1
//    printf("%d\n", p[0]);//p[0]->*(p+0),是1
//    return 0;
//}


//int main()
//{
//    int a[5][5];//二维数组,5行5列
//    int(*p)[4];//int(*)[4]
//    p = a;//a是int(*)[5],p是int(*)[4],,,将a放入p中,p仍指向首元素的地址
//    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//    //打印结果为11111111111111111111111111111100,,,-4
//    //&p[4][2]->*(*(p+4)+2),即4行2列
//    //但是p是[4],p每次只前进4个字节,而a是5个字节,所以&p[4][2]只是a[3][2]
//    //&a[4][2]就是&a[4][2],小地址-大地址=-4,   -4的原码为10000000000000000000000000000100
//    //                                               反码11111111111111111111111111111011
//    //                                               补码11111111111111111111111111111100
//    //在地址,直接打印%p为11111111111111111111111111111100,%d时需要吧补码再次改为原码仍为-1
//    return 0;
//}

//int main()
//{
//    int aa[2][5] = { 1,2,3,4,5,6,7,8,8,10 };
//    int* ptr1 = (int*)(&aa + 1);//&aa+1,跳过整个数组,此时是数组,被(int*)强制类型转换
//    int* ptr2 = (int*)(*(aa + 1));//数组名是首元素地址,aa+1第一行地址+1,是跳过二维数组的第一行
//    //进入第二行,是指向6,*(aa+1)->aa[1],即第二行的数组名,首元素6的地址,此时就是int的6
//    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10 5
//    return 0;
//}


//int main()
//{
//    char* a[] = { "work","at","alibaba" };
//    //a是指针数组,每个元素是指针,每个元素分别是(char*,char*,char*),分别存放,work,at,alibaba
//    char** pa = a;//将a的三个指针的地址传给pa,二级指针,指向第一个char*的首元素地址
//    pa++;//此时是第二个char*
//    printf("%s\n", *pa);//at   
//    //%s打印字符串,解引用pa(此时是第二个char*)
//    return 0;
//}

int main()//指针是连续存放的
{
    char* c[] = { "ENTER","NEW","POINT","FIRST" };//将这些元素依次存放在c指针中,
    //c的指针分别用char*,char*char*,char*接收
    char** cp[] = { c + 3,c + 2,c + 1,c };//c表示首元素地址,与*c的c对应
    //把c的char*,char*char*,char*分别存放在c,c+1,c+2,c+3中(注意顺序)
    char*** cpp = cp;//把cp放在指针ccp中,顺序是c,c+1,c+2,c+3
    printf("%s\n", **++cpp);//POINT
    printf("%s\n", *-- * ++cpp + 3);//ER
    //优先级决定先算++cpp,刚刚的cpp指向c+2,++之后变为指向c+1,解引用变为c+1,
    //c+1进行--,变为c,解引用是char*,char*指向的ENTER的E,再+3,变为E
    printf("%s\n", *cpp[-2] + 3);//ST
    //*cpp[-2]+3->**(cpp-2)+3,即为上一个打印时的c+1为cpp,
    //-2变为c+3,两次解引用指向FINRST,+3后指向ST
    printf("%s\n", cpp[-1][-1] + 1);//EW
    // cpp[-1][-1] + 1-->*(*(cpp-1)-1)+1,cpp此时为c+1,-1变为c+2,解引用变为point的char*,
    //-1变为new的char*,解引用变成new,+1为ew 
    return 0;
}

举报

相关推荐

0 条评论