指针和数组辨析难点汇总

这里列举了一些关于一维数组、二维数组、字符数组、指针、多级指针方面的辨析和笔试题,可复制代码后取消注释编译运行,如有问题或不解处欢迎大家交流。

Tips:

数组名的意义:

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。

//int main()
//{
//一维数组
//    int a[] = { 1,2,3,4 };
//    printf("%d\n", sizeof(a));                    //16    此处代表整个数组大小
//    printf("%d\n", sizeof(a + 0));                //4/8    首元素地址的大小 
//    printf("%d\n", sizeof(*a));                    //4        首元素大小int型,4字节
//    printf("%d\n", sizeof(a + 1));                //4/8    首元素地址为int*,+1后跳过4字节,为第二个元素地址大小
//    printf("%d\n", sizeof(a[1]));                //4        第二个元素大小int型,4字节
//    printf("%d\n", sizeof(&a));                    //4/8   &a虽然是数组的地址,sizeof计算的依然是一个地址的大小        
//    printf("%d\n", sizeof(*&a));                //16    *&抵消,仍是数组的大小
//    printf("%d\n", sizeof(&a + 1));                //4/8    跳过整个数组后的地址
//    printf("%d\n", sizeof(&a[0]));                //4/8    首元素地址的大小
//    printf("%d\n", sizeof(&a[0] + 1));            //4/8    第二个元素地址大小

//字符数组
//    char arr[] = { 'a','b','c','d','e','f' };
//    printf("%d\n", sizeof(arr));                //6        数组中未存放'\0'
//    printf("%d\n", sizeof(arr + 0));            //4/8    首元素地址大小
//    printf("%d\n", sizeof(*arr));                //1        首元素大小,char占1字节
//    printf("%d\n", sizeof(arr[1]));                //1        第二个元素大小,char占1字节
//    printf("%d\n", sizeof(&arr));                //4/8    数组地址
//    printf("%d\n", sizeof(&arr + 1));            //4/8    跳过整个数组后的地址,若+2则跳过12字节
//    printf("%d\n", sizeof(&arr[0] + 1));        //4/8    第二个元素地址大小

//int mystrlen(char* str) 
//    {
//        char* end = &str[0], * start = &str[0];
//        while (*end != '\0')
//        {
//            end++;
//        }
//        return end - start;
//    }

//    char arr[] = { 'a','b','c','d','e','f' };
//    printf("%d\n", strlen(arr));                //随机    从首元素地址出发找'\0'
//    printf("%d\n", strlen(arr + 0));            //随机    从首元素地址出发找'\0'
//    printf("%d\n", strlen(*arr));                //err    将a-97当作地址传参出现错误
//    printf("%d\n", strlen(arr[1]));                //err    将b-98当作地址传参出现错误
//    printf("%d\n", strlen(&arr));                //随机  取出数组地址,类型为char(*)[6],传参后类型变为char*
//    printf("%d\n", strlen(&arr + 1));            //随机    取出跳过整个数组后的地址,是上一个随机值-6
//    printf("%d\n", strlen(&arr[0] + 1));        //随机    从第二个元素地址出发找'\0',是第一个随机值-1

//    char arr[] = "abcdef";
//    printf("%d\n", sizeof(arr));                //7
//    printf("%d\n", sizeof(arr + 0));            //4/8
//    printf("%d\n", sizeof(*arr));                //1
//    printf("%d\n", sizeof(arr[1]));                //1
//    printf("%d\n", sizeof(&arr));                //4/8
//    printf("%d\n", sizeof(&arr + 1));            //4/8
//    printf("%d\n", sizeof(&arr[0] + 1));        //4/8    第二个元素地址大小

//    char arr[] = "abcdef";
//    printf("%d\n", strlen(arr));                //6
//    printf("%d\n", strlen(arr + 0));            //6
//    printf("%d\n", strlen(*arr));                //err    将a-97当作地址传参出现错误
//    printf("%d\n", strlen(arr[1]));                //err    将b-98当作地址传参出现错误
//    printf("%d\n", strlen(&arr));                //6        取出数组地址,仍然从a出发找'\0'
//    printf("%d\n", strlen(&arr + 1));            //随机    
//    printf("%d\n", strlen(&arr[0] + 1));        //5        从第二个元素b地址出发找'\0'
    
//    char* p = "abcdef";                            //p中存放的是a的地址
//    printf("%d\n", sizeof(p));                    //4/8    a的地址大小
//    printf("%d\n", sizeof(p + 1));                //4/8    b的地址大小
//    printf("%d\n", sizeof(*p));                    //1        a的大小,类型为char
//    printf("%d\n", sizeof(p[0]));                //1        p[0]<=>*(p+0)<=>*p,同上
//    printf("%d\n", sizeof(&p));                    //4/8    变量p的地址的大小
//    printf("%d\n", sizeof(&p + 1));                //4/8    跳过p后的地址的大小
//    printf("%d\n", sizeof(&p[0] + 1));            //4/8    b的地址大小

//    char* p = "abcdef";
//    printf("%d\n", strlen(p));                    //6        从首元素a地址出发找'\0'
//    printf("%d\n", strlen(p + 1));                //5        从第二个元素b地址出发找'\0'
//    printf("%d\n", strlen(*p));                    //err    p中存放的是a的地址,解引用即为a,将a-97当作地址传参出现错误
//    printf("%d\n", strlen(p[0]));                //err    p[0]<=>*(p+0)<=>*p,同上
//    printf("%d\n", strlen(&p));                    //随机    从变量p地址出发找'\0'
//    printf("%d\n", strlen(&p + 1));                //随机    从跳过p后的地址出发找'\0'(同上无关,因为p的4个字节中是否有'\0'未知)
//    printf("%d\n", strlen(&p[0] + 1));            //5        从第二个元素b地址出发找'\0'

//二维数组
//    int a[3][4] = { 0 };
//    printf("%d\n", sizeof(a));                    //48    3*4*sizeof(int)
//    printf("%d\n", sizeof(a[0][0]));            //4        第一行第一个元素大小
//    printf("%d\n", sizeof(a[0]));                //16    a[0]可理解为第一行的数组名,单独放在sizeof内部计算的是整个第一行的大小
//    printf("%d\n", sizeof(a[0] + 1));            //4/8    此处a[0]指第一行的首元素地址,+1为第一行第二个元素的地址
//    printf("%d\n", sizeof(*(a[0] + 1)));        //4        第一行第二个元素的大小,类型为int
//    printf("%d\n", sizeof(a + 1));                //4/8    a是二维数组首元素地址,即第一行元素的地址,+1为第二行元素的地址
//    printf("%d\n", sizeof(*(a + 1)));            //16    *(a+1)<=>a[1],第二行元素的大小
//    printf("%d\n", sizeof(&a[0] + 1));            //4/8    &a[0]取出第一行的地址,+1为第二行元素的地址
//    printf("%d\n", sizeof(*(&a[0] + 1)));        //16    第二行元素的大小
//    printf("%d\n", sizeof(*a));                    //16    a是第一行元素的地址,解引用后为第一行元素的大小
//    printf("%d\n", sizeof(a[3]));                //16    sizeof()内部的表达式不计算!类型为int[4],即使不存在仍可通过类型得结果
    
//    return 0;
//}

以下是部分笔试题及解析:

Tips:

%d 有符号10进制整数

%i 有符号10进制整数

%o 无符号8进制整数

%u 无符号10进制整数

%x 无符号的16进制数字,并以小写abcdef表示

%X 无符号的16进制数字,并以大写ABCDEF表示

%F/f 浮点数

%E/e 用科学表示格式的浮点数

%g 使用%f和%e表示中的总的位数表示最短的来表示浮点数 G 同g格式,但表示为指数

%c 单个字符

%s 字符串

//int main()
//{
//    int a[4] = { 1, 2, 3, 4 };
//    int* ptr1 = (int*)(&a + 1);
//    int* ptr2 = (int*)((int)a + 1);//a为首元素地址,地址+1是+1字节!!!    
//    printf("%x,%x", ptr1[-1], *ptr2);//ptr1[-1]<=>*(ptr1-1),整型指针-1解引用后向前跳4字节
//                                     //*ptr2 整型指针解引用向后访问4字节
//    return 0;
//    //小端存储:|01 00 00 00 |02 00 00 00 |03 00 00 00 |04 00 00 00|
//    //            &a |00 00 00 02|                       |          &a+1
//    //            (int)a + 1                             ptr1-1          ptr1
//    //读取:    *ptr2:0x02000000                 *(ptr1-1):0x00000004
//    //输出结果:4,2000000  (%x 无符号的16进制数字,并以小写abcdef表示,打印有效数字)
//}

//int main()
//{
//    int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式!!!其结果为最后一项,如(0,1)结果为1
//    int* p;                                     //1    3
//    p = a[0];                                 //5    0
//    printf("%d", p[0]);                         //0    0        最终:p[0]为1
//    return 0;
//}

//int main()
//{
//    int a[5][5];
//    int(*p)[4];
//    p = a;                //a是首元素地址int(*)[5],p是int(*)[4],存在类型差异                    
//    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//    //|0 0 0 0|0                            低地址-高地址=-4
//    // 0 0 0|0 0                原码    10000000 00000000 00000000 00000100    %d有符号数打印-4
//    // 0 0|0 0 0                反码    11111111 11111111 11111111 11111011
//    // 0|0 0(0)0    p[4][2]        补码    11111111 11111111 11111111 11111100    %p为地址,无符号
//    // 0 0(0)0 0    a[4][2]                F   F     F   F      F   F       F   C    %p将补码直接解析成原码,并以十六进制打印
//    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 main()
//{
//    char* a[] = { "work","at","alibaba" };
//    char** pa = a;
//    pa++;
//    printf("%s\n", *pa);//at
//    return 0;
//}
//***重点题型***
//int main()
//{
//    char* c[] = { "ENTER","NEW","POINT","FIRST" };
//    char** cp[] = { c + 3,c + 2,c + 1,c };
//    char*** cpp = cp;                                
//    printf("%s\n", **++cpp);                        //POINT
//    printf("%s\n", *-- * ++cpp + 3);                //ER
//    printf("%s\n", *cpp[-2] + 3);                   //ST
//    printf("%s\n", cpp[-1][-1] + 1);                //EW
//    //画图分析
//    //注意:1.++cpp一次cpp已被更改     2.++优先级高于+  3.cpp[-1][-1]<=>*(*(cpp-1)+1)
//    return 0;
//}

最后一题画图分析可解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值