栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【指针】综合练习题总结分析

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【指针】综合练习题总结分析

        本文是针对B站鹏哥c语言教程指针练习的个人总结笔记,学习复习用。

练习一
int main()
{
 int a[3][4];
 printf("%dn",sizeof(a));
 printf("%dn",sizeof(a[0]));
 printf("%dn",sizeof(a[0]+1));
 printf("%dn",sizeof(*(a[0]+1)));
 printf("%dn",sizeof(a+1));
 printf("%dn",sizeof(*(a+1));
 printf("%dn",sizeof(&a[0]+1));
 printf("%dn",sizeof(*(&a[0]+1)));
 printf("%dn",sizeof(*a));
 printf("%dn",sizeof(a[3]));

return 0;
}

       

        一道一道来分析:
printf("%dn",sizeof(a));

        首先看第一小题,数组名单独放在sizeof内,计算整个数组的内存大小,该数组共有3*4 = 12个int元素,则结果为48。

printf("%dn",sizeof(a[0]));
printf("%dn",sizeof(a[0]+1));
printf("%dn",sizeof(*(a[0]+1)));

        a[0]与a[0]+1区别在哪?

        a[0]是原二维数组的行数组,是一个一维数组名,相当于其首元素的地址,是一个int指针类型,a[0] + 1就相当于&a[0][0]+1即&a[0][1]。

         a[0]单独置于sizeof内时,计算的就是该一维数组的内存大小(前面提过),即4*4 = 16。但是a[0]+1在sizeof内就是计算一个指针变量的内存大小,即4或8。

注意:指针变量大小和cpu寻址长度相关,32位就是4个字节,64位就是8个字节。

        那么*(a[0]+1),不言而喻,就是*(&a[0][1])即a[0][1],其内存大小为4。

printf("%dn",sizeof(a+1));
printf("%dn",sizeof(*(a+1));

         a是一个二维数组名,一维数组指针类型,相当于&a[0],就是第一行的地址,则a+1即&a[0]+1,指针的增减运算是与指针类型密切相关的,这里加1就是地址偏移了一个含有四个int元素的一维数组的内存大小对应字节数,讲的不太明白的亚子,看图!!

        *(a+1)即*(&a[0]+1)即*(&a[1])即a[1],计算的就是一维数组a[1]内存大小即16。

 ​

printf("%dn",sizeof(&a[0]+1));

        计算的是&a[1],指针呗,结果就是4或8。

printf("%dn",sizeof(*(&a[0]+1)));

        计算的就是a[1],同*(a+1),结果为16。

printf("%dn",sizeof(*a));

        *a即*(&a[0])即a[0],4*4 = 16。

printf("%dn",sizeof(a[3]));

        欸,不对劲呀,你这不越界访问了吗??你定义的二维数组行下标不也就0,1,2吗?好像是哦......但是

注意3:sizeof不对括号内表达式进行计算,只是用以计算操作数所占内存大小。

        什么意思呢?在这里,定义了一个二位数组a[3][4],内存空间中开辟了一段大小为48的连续内存 :

        &a[i]就是以&a[0]为出发点,向后偏移i个单位,这里的单位的字节数由指针类型所确定,如&a[i]为一维数组指针型,内含4个int,则一单位就是16。a[3]就是在&a[2]+1处向后找了一块16字节的内存确立为一个含4int的一维数组,将其放入sizeof内并没有去访问并操作该数组(实际上不存在),单纯地计算其对应类型(假设存在)所占内存大小而已,结果就是16。

        PS:如果是a[-1]呢?结果也是一样的。

小总结:

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

2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址,也是一个数组指针类型。

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

至此,练习一部分结束


练习二    (更新中...)     

int a[4] = {1, 2, 3, 4};
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);

printf("%x,%x",ptr1[-1],*ptr2);


        &a取的是整个数组的地址,相当于一个一维数组指针类型,加1即为&a[1]。

                    

         (int *) 强制将int *p() 转化为int *p,ptr1[-1]相当于在ptr1[0]上向左偏移一个int地址单位,其值就与a[3]相同,输出结果就为4000000。

        (int)a + 1不同于a + 1,后者是Int指针型加1,地址增加4字节,而前者是int型加1,地址增加1字节。这里输出是以%x也就是16进制输出的,若是小端存储的话,*ptr2拿出来的就是四个字节的0x00000002对应的数0x02000000,输出结果就为2000000。

        大端模式(Big-endian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,即正序排列,如存放0x2就为00 00 00 02。

        小端模式(Little-endian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,即逆序排列,如存放0x2就为02 00 00 00。

 

      

 

int a[3][2] = {(0,1),(2,3),(4,5)};
int*p;
p = a[0];
printf("%d",p[0]);

        这里有陷阱,注意在初始化这个二维数组时里面的括号是( )而非{ },( )里面的逗号表达式一算出来就相当于int a[3][2] = {1,3,5}。p = a[0]就是把a[0]这个一维数组的地址放到p处,则p[0]就为a[0][0]即1。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/779659.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号