V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waiaan
V2EX  ›  C

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

  •  
  •   waiaan · 2019-10-16 10:15:36 +08:00 · 3871 次点击
    这是一个创建于 1866 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 10:23:15 +08:00
    第一个是数组第一个元素的指针,第二个是数组的指针,打印出来的结果当然一样
    kljsandjb
        2
    kljsandjb  
       2019-10-16 10:27:19 +08:00 via iPhone
    c 语言的 legacy
    Rasphino
        3
    Rasphino  
       2019-10-16 10:30:26 +08:00
    int *p;

    int (*p)[5];
    waiaan
        4
    waiaan  
    OP
       2019-10-16 10:32:04 +08:00
    @stebest
    所以 a 还不算一个变量?
    dawn009
        5
    dawn009  
       2019-10-16 10:49:59 +08:00
    @waiaan #4 第一个有隐式类型转换
    CRVV
        6
    CRVV  
       2019-10-16 10:55:27 +08:00
    a 是一个变量,类型是 int[5]

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

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

    @stebest

    我查了一下资料,数组名并不是指针,以前理解错了。
    v2bee
        13
    v2bee  
       2019-10-16 12:12:29 +08:00
    《 C 专家编程》里作者说“数组名是指针”的这一页撕下来...
    misaka19000
        14
    misaka19000  
       2019-10-16 12:14:30 +08:00
    反编译一下,看汇编就清楚了
    stebest
        15
    stebest  
       2019-10-16 14:04:01 +08:00
    @v2bee 确实应该当众处刑
    opensail
        16
    opensail  
       2019-10-16 14:05:40 +08:00
    @stebest 还是 Primer(没有 plus 这本书好,简直是圣经
    shfanzie
        17
    shfanzie  
       2019-10-16 15:16:59 +08:00
    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 15:55:55 +08:00   ❤️ 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 16:21:57 +08:00
    @raysonx
    赞,谢谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   928 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:54 · PVG 03:54 · LAX 11:54 · JFK 14:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.