求问一个关于数组和指针的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waiaan
V2EX    C

求问一个关于数组和指针的问题

  •  
  •   waiaan 2019 年 10 月 16 日 4413 次点击
    这是一个创建于 2345 天前的主题,其中的信息可能已经有所发展或是发生改变。
    void main(void) { int a[5] = {1, 2, 3, 4, 5}; printf("%p\n", a); printf("%p\n", &a); } 

    为什么打印出来结果会是一样的?

    谢谢。

    19 条回复    2019-10-16 16:21:57 +08:00
    stebest
        1
    stebest  
       2019 年 10 月 16 日
    第一个是数组第一个元素的指针,第二个是数组的指针,打印出来的结果当然一样
    kljsandjb
        2
    kljsandjb  
       2019 年 10 月 16 日 via iPhone
    c 语言的 legacy
    Rasphino
        3
    Rasphino  
       2019 年 10 月 16 日
    int *p;

    int (*p)[5];
    waiaan
        4
    waiaan  
    OP
       2019 年 10 月 16 日
    @stebest
    所以 a 还不算一个变量?
    dawn009
        5
    dawn009  
       2019 年 10 月 16 日
    @waiaan #4 第一个有隐式类型转换
    CRVV
        6
    CRVV  
       2019 年 10 月 16 日
    a 是一个变量,类型是 int[5]

    数组是一段连续的内存上放了多个元素,很多语言的数组( std::vector )是一个 struct,包含了这段内存的地址,数组的长度容量这些信息。

    但是 C 的数组只是那一段用来放元素的内存,没有其它的东西了,数组的地址,数组本身都是指那一段内存。
    stebest
        7
    stebest  
       2019 年 10 月 16 日
    @waiaan 指针不是变量?
        8
    stebest  
       2019 年 10 月 16 日
    @waiaan 值一样,但类型不一样,移动的步长不一样!数组指针移动一个位置的话,就跳过了整个数组,元素指针移动一个位置,就跳一个元素
    opensail
        10
    opensail  
       2019 年 10 月 16 日
    测试结果是 0x7ffd361b7420
    0x7ffd361b7420
    opensail
        11
    opensail  
       2019 年 10 月 16 日
    @opensail
    我得理解 a 是一个指针,指向了数组首元素,第一个输出是指针 a 本身得地址,第二个输出是指针 a 所指向元素得地址,也是数组第一个元素,小白回答,望指教,已收藏问题
    waiaan
        12
    waiaan  
    OP
       2019 年 10 月 16 日
    @opensail

    @stebest

    我查了一下资料,数组名并不是指针,以前理解错了。
    v2bee
        13
    v2bee  
       2019 年 10 月 16 日
    《 C 专家编程》里作者说“数组名是指针”的这一页撕下来...
    misaka19000
        14
    misaka19000  
       2019 年 10 月 16 日
    反编译一下,看汇编就清楚了
    stebest
        15
    stebest  
       2019 年 10 月 16 日
    @v2bee 确实应该当众处刑
    opensail
        16
    opensail  
       2019 年 10 月 16 日
    @stebest 还是 Primer(没有 plus 这本书好,简直是圣经
    shfanzie
        17
    shfanzie  
       2019 年 10 月 16 日
    void main(void)
    {
    int a[5] = {1, 2, 3, 4, 5};
    printf("%p\n", a);
    printf("%p\n", &a);
    }

    printf("%p\n", a); 打印 a 的地址,a 的地址就是它本身,指向 int[5]的地址;
    printf("%p\n", &a); 这个地方的&是取址运算符,也就意味着取一个变量的地址并付给指针变量。

    所以以上两句打印的同一个地址。
    raysonx
        18
    raysonx  
       2019 年 10 月 16 日   3
    好久没答语言相关的问题了。 @stebest 和 9 楼的链接是对的。认同“数组名是指针”的建议把以前看的书撕掉。

    C 语言里数组就是数组,在类型上指针是不一样的。当你定义 int arr[10]; 的时候,arr 的类型就是 int[10],sizeof(arr)的结果等于 sizeof(int) * 10 而不是 sizeof(int*)。

    问题在于,在很多情况下 C 语言的数组可以退化(decay)成指向第一个(也可以说第 0 个)元素的指针,比如以参数形式传给另一个函数的时候,比如 foo(arr),或者向另一个指针赋值的时候,比如 int *p = arr。这种情况下的 arr 等价于&arr[0]。C 语言的这种特性可以视为隐式类型转换或者语法糖。如果这时你用 sizeof 去测试 p 或者 foo 函数的参数,你会得到等同于 sizeof(int*)的值也就是指针的长度( 32 位系统下为 4,64 位系统下为 8 )。

    而 &arr 会返回指向整个数组的指针,类型为 int(*)[10]。因为 C 语言的数组实质就是元素组成的连续内存,所以数组的地址和第一个元素的地址在数值上是相等的,这也是为什么 &arr 在数值上等同于 &arr[0]。但注意它们的类型是不同的。如果你对&arr 进行指针运算,比如 &arr + 1,则计算得到的新地址会指向整个数组之后的下一个字节,而不是指向 arr[1]。
    waiaan
        19
    waiaan  
    OP
       2019 年 10 月 16 日
    @raysonx
    赞,谢谢!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5748 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 06:40 PVG 14:40 LAX 23:40 JFK 02:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86