数组名和数组名取地址的区别

本文探讨了C语言中数组名与指针的区别与联系,通过实例展示了数组名作为表达式时的特殊性质。文章解释了为什么`str`和`&str`在某些情况下值相同但类型不同,以及`str+1`和`&str+1`的内存偏移差异。同时,还分析了汇编代码以进一步理解内存布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

遇到了一个坑,记录一下。

#include <stdio.h>

char str[10];

int main()
{
    printf("str    = %p\n", str);
    printf("&str   = %p\n", &str);
    printf("str+1  = %p\n", str+1);
    printf("&str+1 = %p\n", &str+1);
    return 0;
}

运行结果:

str    = 0x556749e01018
&str   = 0x556749e01018
str+1  = 0x556749e01019
&str+1 = 0x556749e01022

数组名的值是一个指针常量,也就是数组第一个元素的地址,它的数据类型取决于数组元素的类型,如果是int数组,那么数组名的类型就是指向int的常量指针。str等价于&str[0]strchar型数组,则str就是指向char型的指针常量,所以str+1就是str + sizeof(char)
但是有一个例外,当数组名作为sizeof或者&的操作数时,数组名不是一个指针常量。sizeof(str)等于10,是数组的长度,而不是指向数组的指针的长度。&str是指向数组的指针,而不是指向指针常量的指针。虽然str&str的值相同,但是二者是不同的指针类型,str指向str[0]的指针,而&str是指向数组的指针,因此&str+1等价于str + sizeof(str)

gcc -S test.c的汇编结果如下:

        .file   "test.c"
        .text
        .comm   str,10,8
        .section        .rodata
.LC0:
        .string "str    = %p\n"
.LC1:
        .string "&str   = %p\n"
.LC2:
        .string "str+1  = %p\n"
.LC3:
        .string "&str+1 = %p\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        leaq    str(%rip), %rsi  // 对应str
        leaq    .LC0(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        leaq    str(%rip), %rsi  // 对应&str,可见汇编是一样的
        leaq    .LC1(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        leaq    1+str(%rip), %rax // 对应str+1
        movq    %rax, %rsi
        leaq    .LC2(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        leaq    10+str(%rip), %rax // 对应&str+1
        movq    %rax, %rsi
        leaq    .LC3(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值