c/c++语言开发共享数组a和&a的起始地址

在以下两行中,

char a[5]={1,2,3,4,5}; char *ptr=(char *)(&a+1); printf("%d",*(ptr-1)); 

这在屏幕上打印5个。当使用a而不是&a时,

 char a[5]={1,2,3,4,5}; char *ptr=(char *)(a+1); printf("%d",*(ptr-1)); 

这打印1

a和&a都是数组的起始地址。所以为什么这有区别?

char * ptr =&a + 1;

显示警告。

    既然你看起来很陌生,那么让我用简单的语言向你解释,而不是去做严谨的解释。

    你看,对于你上面的程序, a&a将具有相同的数值 ,我相信这就是你的整个混乱所在。你可能想知道如果它们是相同的,下面的内容应该在两种情况下给出下一个地址 ,通过指针算术:

     (&a+1) and (a+1) 

    但事实并非如此! 数组的基址 (此处为a )和数组的地址不相同! a&a可能在数字上相同,但它们不是同一类型a的类型为char*&a的类型为char (*)[5] ,即&a是指向(地址)和大小为5的数组的指针。但是,如您所知,a是第一个元素地址。数字 。在数量上,它们与你在下面使用^的插图中看到的相同。

    但是当你递增这两个指针/地址时,即(a+1)(&a+1) ,算法完全不同。而在第一种情况下它会“跳转”到数组中下一个元素的地址,在后一种情况下,它会跳过5个元素,就像5个元素的数组大小一样! 。现在明白了?

      1 2 3 4 5 ^ // ^ stands at &a 1 2 3 4 5 ^ // ^ stands at (&a+1) 1 2 3 4 5 ^ //^ stands at a 1 2 3 4 5 ^ // ^ stands at (a+1) 

    以下将给出关于未指定数组绑定的错误,因为未明确指定大小,如下所示,当遇到类似(&a + 1)之类的程序时,程序将不知道“跳转”到多少元素。

     char a[]={1,2,3,4,5}; char *ptr=(char *)(&a+1); //(&a+1) gives error as array size not specified. 

    现在到你将指针/地​​址递减为(ptr-1) 。在第一种情况下,在你来到减量部分之前,你应该知道在它上面的语句中发生了什么,它被转换为类型char*

     char *ptr=(char *)(&a+1); 

    这里发生的是你“剥离” typechar (*)[5]的原始type (&a+1) ,然后将其转换为类型char* ,它与a的类型相同,即基数数组的地址。(再次注意数组的基地址和数组的地址之间的区别。在上面的语句中进行强制转换和赋值后,接着是printf()的递减, ptr现在给出了内存位置数组的最后一个元素,即5

      1 2 3 4 5 ^ // ^ stands at location of 5, so *ptr gives 5 

    因此,当您将指针ptr递减为*(ptr-1)后取消引用时,它会按预期打印值5

    最后,将其与第二种情况进行对比,其中印有1看看我使用符号^给出的插图。 当你将a增加为a+1 ,它指向数组的第二个元素,即2并且你已将此地址分配给ptr .So当你将ptr减为(ptr-1) ,它会跳回一个元素,现在指向数组的第一个元素,即1在第二种情况下解除引用ptr给出1

      1 2 3 4 5 ^ // ^ stands at address of 1, so *ptr gives 1 

    希望这一切都清楚。

    数组不是指针! 有关更多信息,请阅读comp.lang.c FAQ的第6部分 。

    让我们先来看看你的第二个案例吧,因为它更“正常”而且惯用。 逐行:

    现在,让我们逐行解决第一个案例:

    最后,原因char *ptr=&a+1; 发出警告是因为C要求指针类型之间的转换具有显式强制转换。 如上所述, &a的类型为char (*)[5]而不是 char * ,因此要将该值赋给char *变量,您需要显式强制转换。

    不同之处在于您获得的指针类型:

    向指针添加整数时,指针移动的字节数由指针指向的对象指针的类型决定。 如果指针指向char ,则添加N会使指针前进N个字节。 如果指针指向一个包含五个char的数组,则添加N会使指针前进5*N字节。

    这正是你得到的差异:你的第一个例子将指针推进到一个超过数组末尾的元素(这是合法的),然后将其移回最后一个元素。 另一方面,您的第二个示例将指针前进到第二个元素,然后将其移回指向数组的初始元素。

    你遇到的是指针算术的微妙之处。

    编译器将“a”视为指向char的指针 – 一个大小为1字节的实体。 向此处添加1会产生一个指针,该指针会增加实体的大小(即1)。

    编译器将“&a”视为指向字符数组的指针 – 一个大小为5字节的实体。 向此处添加1会产生一个指针,该指针会增加实体的大小(即5)。

    这就是指针算法的工作原理。 将一个指针添加到指针会使其增加指针所指定类型的大小。

    当然,有趣的是,当评估“a”或“&a”的值时,在解除引用时,它们都会评估到相同的地址。 这就是你看到你所做的价值的原因。

    数组“衰减”成指向第一个元素的指针。 因此,获取a的地址会给出一个指向5个字符数组的指针,就像声明char[][5] 。 并且递增此指针前进到char[][5]数组的下一个元素 – 一次是5个字符。 这与递增从char[5]数组衰减的指针(即一次只有一个字符)不同。

    需要了解更多c/c++开发分享数组a和&a的起始地址,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享数组a和&a的起始地址相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/980179.html

      (0)
      上一篇 2021年12月13日
      下一篇 2021年12月13日

      精彩推荐