V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

对于 arr[],&arr 与 arr 的%p 居然是相同的,该怎么理解?

  •  
  •   Newyorkcity · 2018-10-18 15:25:30 +08:00 · 1750 次点击
    这是一个创建于 1988 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include<stdio.h>
    int main(void){
    	int arr[] = {1,2,3};
    	printf("arr=%p,&arr=%p\n",arr,&arr);
    	printf("*arr=%d,*&arr=%d(%p)\n",*arr,*&arr,*&arr);
    	return 0;
    }
    

    然而

    #include<stdio.h>
    int main(void){
    	int a = 0;
    	int *p = &a;
    	int *pp = &p;
    	printf("&a=%p,p=%p,pp=%p\n",&a,p,pp);
    	return 0;
    }
    

    这里 pp 和 p 的%p 是不相同的.

    对于第二个程序不相同我就很好理解了,p 中存放变量 a 的地址,pp 存放指针 p 的地址...

    而对于第一个程序,arr 存放数组首元素地址,&arr 则是变量 arr 的地址.&arr 和 arr 显然不应该一样..

    但它们就是一样了,这我就无法理解

    第 1 条附言  ·  2018-10-18 16:43:31 +08:00
    简单一点,假定内存给每个字节分配一个地址,对 char s[]={'a','b'},假定地址 01 的空间存储'a'对应的 ASCII 码,地址 02 的空间存储'b'对应的 ASCII 码,那么 s 应该分到 03-10 共 8 个 byte 作为它的空间用来存储 01(数组首元素的地址),那么 s 的地址,也就是&s 应当是 03..如果 s 这个变量的地址和&s 相等,那 01-08 共 8 个字节用来存储数组首元素'a'的地址 01,地址为 01 和 02 的字节就必须为 0,那还怎么存储'a'和'b'的 ASCII 码?
    或者说,使用了什么特别的规定或者方法解决了这个矛盾?或者说我考虑的这个矛盾实际上不存在?
    谢谢
    11 条回复    2018-10-19 00:19:27 +08:00
    Yourshell
        1
    Yourshell  
       2018-10-18 15:34:17 +08:00 via iPhone
    数组的地址不就是首元素的地址吗
    kkhaike
        2
    kkhaike  
       2018-10-18 15:35:22 +08:00
    我能告诉你 arr 这个变量的地址就是他的首元素地址吗
    kljsandjb
        3
    kljsandjb  
       2018-10-18 15:53:40 +08:00 via iPhone
    约定俗成的
    Newyorkcity
        4
    Newyorkcity  
    OP
       2018-10-18 16:42:12 +08:00
    @kkhaike
    简单一点,假定内存给每个字节分配一个地址,对 char s[]={'a','b'},假定地址 01 的空间存储'a'对应的 ASCII 码,地址 02 的空间存储'b'对应的 ASCII 码,那么 s 应该分到 03-10 共 8 个 byte 作为它的空间用来存储 01(数组首元素的地址),那么 s 的地址,也就是&s 应当是 03..如果认为 s 这个变量的地址就是数组首元素的地址,那 01-08 共 8 个字节用来存储数组首元素'a'的地址 01,地址为 01 和 02 的字节就必须为 0,那还怎么存储'a'和'b'的 ASCII 码?
    wevsty
        5
    wevsty  
       2018-10-18 16:51:34 +08:00   ❤️ 1
    @Newyorkcity

    1、不用假定,内存里面的每个 byte 都一定有地址对应。
    2、在你的例子里,char s[]作为数组 s 本身可以理解为只有编译器知道的一个地址的别名,这个地址本身不占用内存空间,只有数组里面储存的内容才占用空间。
    misaka19000
        6
    misaka19000  
       2018-10-18 16:52:04 +08:00
    append 看晕了,不过隐约感觉楼主好像把 bit 和 byte 搞混了,1byte = 8bits
    Newyorkcity
        7
    Newyorkcity  
    OP
       2018-10-18 16:55:12 +08:00
    @misaka19000 额..应该没有吧 8 个 byte 用来存储一个指针,因为一个指针的数据类型占据 8 个 byte 嘛..
    @wevsty 谢谢!我大概理解了
    innoink
        8
    innoink  
       2018-10-18 16:57:11 +08:00   ❤️ 1
    并不存在一个“单独的” arr 变量。arr 你可以理解为一个**字面量**。意思是,这个 arr 会被当成立即数或者编译期常量来用,并不需要占有一个专门的内存单元。
    kingwl
        9
    kingwl  
       2018-10-18 17:00:36 +08:00
    wevsty
        10
    wevsty  
       2018-10-18 17:04:13 +08:00   ❤️ 1
    @Newyorkcity
    顺便说一句
    指针类型不一定是 8 byte,这取决于机器的指令集。对于 X86 指针类型是 4 byte,对于 X64 来说才是 8 byte,不同的指令集对应的大小是不一定一样的。
    msg7086
        11
    msg7086  
       2018-10-19 00:19:27 +08:00
    「&arr 和 arr 显然不应该一样」
    这是怎么显然的。&arr 和 arr 显然本来就是一样的,唯一区别是类型,但是 arr 会自动转换(退化)成其地址,也就是在读取地址立即量的时候,arr 会自动退化成&arr。

    另外,数组严格来说不能称作「变量」。arr 是「变量名」,但不是「变量」。数组是「一群变量 / 数据」的集合,数组本身不是变量,所以不像变量那样有地址,也不占用内存空间。你可以定义一个零长度的数组,其在内存中不占用任何空间。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3418 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 00:07 · PVG 08:07 · LAX 17:07 · JFK 20:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.