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

C 语言 指针问题

  •  
  •   cio 2017-01-30 20:02:08 +08:00 3807 次点击
    这是一个创建于 3178 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr; /* 指针中的数组地址 */ ptr = var; for ( i = 0; i < MAX; i++) { printf("存储地址: var[%d] = %x\n", i, ptr ); printf("存储值: var[%d] = %d\n", i, *ptr ); /* 移动到下一个位置 */ ptr++; } return 0; } 

    其中的 ptr = var; 这里是把数组 var 的第一个值得地址赋值给了 ptr 指针吗? 那可不可以这样写 ptr = &var[0];

    刚学。可能问的问题弱智了点,还是期望有人解惑..

    31 条回复    2017-02-03 12:43:22 +08:00
    am241
        1
    am241  
       2017-01-30 20:06:06 +08:00
    可以这样写,不过没必要
    stevezjb
        2
    stevezjb  
       2017-01-30 20:07:56 +08:00
    var=&var[0]
    liyvhg
        3
    liyvhg  
       2017-01-30 20:11:11 +08:00 via Android   1
    这两种写法是等价的
    LGA1150
        4
    LGA1150  
       2017-01-30 20:17:08 +08:00 via Android
    一个引用&,一个解引用[],正好抵消
    firebroo
        5
    firebroo  
       2017-01-30 20:22:38 +08:00 via Android
    可以的。
    cio
        6
    cio  
    OP
       2017-01-30 20:26:02 +08:00
    谢谢!理解了。我再去好好看看书..
    Lonely
        7
    Lonely  
       2017-01-30 22:20:19 +08:00 via iPhone
    理一下顺序就是&(var[0])
    sfqtsh
        8
    sfqtsh  
       2017-01-30 22:25:18 +08:00 via Android
    var 的类型是 int [3],是个数组类型, ptr 类型是 int*,是个指针类型,前者可隐含向后者转换,指向其首地址。
    var[0]类型是 int ,所以&var[0]类型就是 int*。
    owt5008137
        9
    owt5008137  
       2017-01-30 22:25:28 +08:00 via Android
    可以,一样的
    NvSylvanas
        10
    NvSylvanas  
       2017-01-30 22:50:32 +08:00
    可以
    lzhCoooder
        11
    lzhCoooder  
       2017-01-30 23:18:02 +08:00
    数组名代表数组首地址,这应该是很重要的一个概念,记住它就不会有疑惑了
    klesh
        12
    klesh  
       2017-01-31 00:16:37 +08:00 via Android
    看的什么书?合格的入门级会直接给多第二种写法,并说明是等效的。
    msg7086
        13
    msg7086  
       2017-01-31 02:17:53 +08:00
    a[b] 就是 *(a+b) 的语法糖。
    &a[b] 自然就是 (a+b) 。
    b 是 0 的情况下,&a[0] 就是 (a+0) 也就是 a 了。
    justyy
        14
    justyy  
       2017-01-31 02:21:02 +08:00
    a[b] 可以写成 b[a]
    424778940
        15
    424778940  
       2017-01-31 02:51:44 +08:00
    数组的名字所指向的地址就是数组第一个元素的地址 所以你直接用名字和取第一个元素的地址 结果应该是一样的
    ryd994
        16
    ryd994  
       2017-01-31 08:57:11 +08:00 via Android
    学深点你就知道 a[i]==*(a+i)
    所以可以用这种办法直接偏移数组
    ryd994
        17
    ryd994  
       2017-01-31 08:59:28 +08:00 via Android   1
    推荐你再零长度数组 https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
    会感觉打开了新世界的大门
    然后乱飞指针无法自拔,直到写出自己都看不懂的代码为止

    我就是这么过来的
    ryd994
        18
    ryd994  
       2017-01-31 09:01:10 +08:00 via Android
    @justyy 不一定,如果 a 和 b 不是一个类型呢?
    zhujinliang
        19
    zhujinliang  
       2017-01-31 10:04:31 +08:00 via iPhone
    我觉得&a[n]写法更好,因为 a 的类型不确定,用数组的形式编译器会自动决定偏移多少
    自己处理指针除非有特殊用途
    introom
        20
    introom  
       2017-01-31 10:22:58 +08:00 via Android
    @ryd994 a,b 当然不是一个类型
    ryd994
        21
    ryd994  
       2017-01-31 12:56:15 +08:00
    @introom 考虑这 short *a=1; long *b=2
    ryd994
        22
    ryd994  
       2017-01-31 12:59:55 +08:00
    @zhujinliang 只要指针类型对,指针加减的偏移量是正确的
    指针加加减减是很正规的用法
    C 规范规定了 a[i]和*(a+i) 是等同的
    introom
        23
    introom  
       2017-01-31 14:42:54 +08:00 via Android
    @ryd994 之前楼上那位的意思应该是说,比如
    int arr = {1,2,3}
    那么, arr[1]和 1[arr]一个意思。

    你的问句是,如果 a,b 不是一个类型呢?
    所以 a,b 是一个类型是什么意思?
    crazyjin
        24
    crazyjin  
       2017-01-31 15:40:01 +08:00
    楼主去看看《 csapp 》的前几章,再看看《 c 陷阱与缺陷》。你会理解 c 的指针的本质,并且见识一些极端复杂的用法。
    snnn
        25
    snnn  
       2017-01-31 18:42:44 +08:00
    @zhujinliang “我觉得&a[n]写法更好,因为 a 的类型不确定,用数组的形式编译器会自动决定偏移多少”

    C 语言中所有类型都是静态的。不存在不确定的类型。
    snnn
        26
    snnn  
       2017-01-31 18:43:22 +08:00
    @ryd994 “考虑这 short *a=1; long *b=2 ”

    你这代码编译不过去。
    mintist
        27
    mintist  
       2017-02-01 15:00:22 +08:00   1
    C 语言中的 **指针** 由两部分构成:地址值和类型。

    地址值就是数字,和汇编中是一样的。

    而类型,在汇编里面是没有的,所以是给 C 语言的编译器看的,在编译期间, C 语言会根据你写的指针类型给它们分配所需要的空间。
    (或者说是弱类型吧,不能说没有类型,而是只有简单的不同位数的整形,浮点型,而没有指针,数组,数组的数组之类的高阶的类型,因为汇编器是比较原始的,没有那么复杂的设计)

    再回到题主的问题:

    “ ptr = var; 这里是把数组 var 的第一个值得地址赋值给了 ptr 指针吗? 那可不可以这样写 ptr = &var[0];”

    这里有两个变量和类型:

    ptr ,它的类型是 int *,为指向整形的指针;
    var ,它的类型是 int [3],为有 3 个整形元素的数组。
    var[0],它的类型是 int ,是*(var+0)的语法糖,所以自然也可以写成*(0+var),进一步的写成 0[var]。
    而 & 表示取地址符的意思,所以 &var[0] 的类型是 int *。

    所以,后两者只是地址值是相等的,其类型是不同的。

    那么类型不同体现在什么地方呢?比如 sizeof(var) = 3*4 =12;而 sizeof(var) = 4 (假设为 32 位的机子)

    当然,还有一些场景,两者会相互转换,比如函数传参数,数组会退化成指针,楼主用 “ C language array & pointer difference ”搜索下估计就能搜到不少

    清楚了类型之后,可以看到,后者的写法是更加正确的,因为左右的类型都是 int *,而前者的写法左右两边类型是不同,有一个类型自动转化在里面,就是地址值过去了,类型给忽略掉了。
    mintist
        28
    mintist  
       2017-02-01 15:02:25 +08:00
    所以,一般个人在写的时候,会把 ptr = var;改成 ptr = (int*)var;,虽然必要性不大,但是这样写只是为了告诉自己,后面就用 int * 类型的指针去访问这段内存吧,的意思
    visionsmile
        29
    visionsmile  
       2017-02-02 20:31:02 +08:00
    @424778940 @lzhCoooder 数组名不是指针,标准里面是这么写的: Here x is a 3 × 5 array of integers. When x appears in an expression, it is converted to a pointer to (the rst of three) ve-membered arrays of integers. In the expression x[i] which is equivalent to *(x+i), x is rst converted to a pointer as described; then x+i is converted to the type of x, which involves multiplying i by the length of the object to which the pointer points,namely ve integer objects.
    lzhCoooder
        30
    lzhCoooder  
       2017-02-03 10:41:42 +08:00
    @visionsmile 数组名当然不是指针,我没说是指针呀...稍微写过一点就知道 sizeof 一个数组和一个指针结果是很不一样的,你搬出标准也只能证明数组名会被隐式转换成数组首地址,这我说的没错呀,一般用起来数组名就是代表首地址...
    visionsmile
        31
    visionsmile  
       2017-02-03 12:43:22 +08:00
    @lzhCoooder “你搬出标准也只能证明数组名会被隐式转换成数组首地址”,那不然还证明啥?“一般用起来数组名就是代表首地址...”,你这样说理解起来会有很大歧义....因为它并不“代表”首地址,只是在使用时会转换为指针。措辞还是要严谨一些啊。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3308 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 11:53 PVG 19:53 LAX 04:53 JFK 07:53
    Do have faith in what you're doing.
    ubao 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