为什么感觉 C 的常量以及指针相关的语法十分令人费解? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
b244183
V2EX    C

为什么感觉 C 的常量以及指针相关的语法十分令人费解?

  •  
  •   b244183 2016-01-13 12:45:17 +08:00 2957 次点击
    这是一个创建于 3560 天前的主题,其中的信息可能已经有所发展或是发生改变。
    常量 常量指针 指向常量的指针 常量 常量指针 指向常量的常量指针

    指针++=++指针 指针++=指针++ ++指针=++指针 *(++指针) *(指针++)

    最近在看 Pointers on C
    感觉这些东西是有规则,但是十分 counterintuitive ,令人费解
    40 条回复    2016-01-14 15:17:26 +08:00
    wizardoz
        1
    wizardoz  
       2016-01-13 13:18:10 +08:00
    首先你要理解指针是一种类型(或多种类型),常量就是不能改变的变量。

    对于 int 来说
    int 是一种类型 int* 是一种类型,只不过这两种类型略微有一点关系而已。

    const int 就是整型常量
    const int* 就是指向整型常量的指针
    int* const 是指向整型的指针常量
    !! 注意其中的区别,一个是指针本身是常量,就是指针变量不能改,一个是指针不是常量可以改,但是指针指向的内存不能改。

    当然还可以
    const int * const
    指向整型常量的指针长量。
    指针的值也不能改,指针指向的地址的内容也不能改。
    congeec
        2
    congeec  
       2016-01-13 13:27:47 +08:00
    你打开的方式不对

    来,告诉我什么是指针数组,什么是数组指针?
    我不知道,但是一看我就知道下面两行代码是什么意思
    int *p[2];
    int (*p)[2];

    同样地,指针++ = 指针++ 这是什么鬼?
    while (*s++ = *t++); // 不过这行复制字符串的代码你肯定能理解

    概念是抽象过的,一般比原来的东西难理解。写几行代码,抓住本质就行了
    k9982874
        3
    k9982874  
       2016-01-13 13:32:48 +08:00
    理解不了我才表示费解,实在不行就去做前端啥的吧,没有指针。
    7emes
        4
    7emes  
       2016-01-13 13:44:06 +08:00
    @wizardoz 发现一个错别字,倒数第二行。
    b244183
        5
    b244183  
    OP
       2016-01-13 13:47:04 +08:00
    @wizardoz
    @k9982874
    @congeec 我知道这些是做什么用的,也会用,但是疑惑为什么语法要设计成这样,都没什么更直观的做法吗
    f7ee9404
        6
    f7ee9404  
       2016-01-13 13:51:43 +08:00
    就是语法糖, c 设计的时候内存和硬盘单位价格非常高,对应现在的电脑没什么大用 代码怎么容易读怎么搞就行。

    i++ 等价于 i=i+1
    congeec
        7
    congeec  
       2016-01-13 13:57:02 +08:00
    @b244183 为嘛要设计成这样?看 spec 吧: ISO/IEC 9899
    多扯两句,据我所知 C 语言基本上是可移植的汇编,为汇编程序员设计的。
    i++有直接对应的汇编指令 incr i
    在汇编里操作数据只能用地址+偏移,自然而然 C 语言里就有指针这个概念了
    kobe1941
        8
    kobe1941  
       2016-01-13 14:14:56 +08:00
    指针和结构体在一起才坑爹%>_<%
    maomaomao001
        9
    maomaomao001  
       2016-01-13 14:25:44 +08:00 via Android
    @wizardoz 好晕啊~~~为什么 C/C++是这种设计方式....
    MCVector
        10
    MCVector  
       2016-01-13 14:50:09 +08:00
    @maomaomao001 to make your life easier.
    young
        11
    young  
       2016-01-13 14:57:14 +08:00

    想起了前几天看到的这个
    wizardoz
        12
    wizardoz  
       2016-01-13 15:09:16 +08:00
    @maomaomao001 其实从语义来讲很对称啊。整个过程只是变量,指针,和 const 三个概念组合以后发生了许多变化。并且组合以后并没有产生与三个概念矛盾的东西。
    所以不应该说 C/C++设计成这样,应该说 C 语言的设计者没有进行很多的设计和封装,而是直接把事情的本质放出来了。
    maomaomao001
        13
    maomaomao001  
       2016-01-13 15:09:41 +08:00 via Android
    @MCVector 骗子。。。
    dorentus
        14
    dorentus  
       2016-01-13 15:11:27 +08:00 via iPhone
    推荐一本书:《征服C指针》
    Kilerd
        15
    Kilerd  
       2016-01-13 15:30:08 +08:00
    你的 C 功底不行啊,指针其实在 C 里面不算是特别难得吧。
    yurivvvvv
        16
    yurivvvvv  
       2016-01-13 15:33:53 +08:00
    我觉得正是 Pointers on C 把这些费解的东西讲的很清楚了。
    b244183
        17
    b244183  
    OP
       2016-01-13 15:52:58 +08:00
    @wizardoz
    @Kilerd
    @yurivvvvv 我想讨论的是语法层面的设计
    jixiangqd
        18
    jixiangqd  
       2016-01-13 16:09:41 +08:00
    看 const 在*前还是*后,*前则是修饰*,*后则是修饰具体类型

    const int *
    int const *
    int * const //只有这个修饰 int
    chmlai
        19
    chmlai  
       2016-01-13 16:18:33 +08:00
    @b244183 那你有想出更好的设计吗?
    k9982874
        20
    k9982874  
       2016-01-13 17:04:21 +08:00
    @b244183
    你要知道 c/c++的内存操作原理就不会不懂了

    c/c++数据传递默认传值,也就是直接做内存 copy ,操作一次就会产生一个内存 copy

    如果是 int 之类的简单类型就算了,如果是 struct 或 class 之类的大对象那内存多少都不够用

    所以为了解决这个问题引入了指针,指针的大小就是一个 unsiged int 的大小, copy 一个 int 的花销和 copy 一个对象的花销比还是很合算的

    这样就避免了值传递时无穷无尽的内存 copy

    还有什么修改对象值,前 const ,后 const 之类的东西都是额外的知识。
    raysonx
        21
    raysonx  
       2016-01-13 17:09:12 +08:00
    一言以蔽之:指保存的只是一整,和 long 、 int 有本,其他皆法糖。
    ffffwh
       
    ffffwh  
       2016-01-13 17:27:20 +08:00 via Android
    “右左法则”

    你还没有见识过 C++的引用、右值引用、指针 /引用与 template 连用等等
    dorentus
        23
    dorentus  
       2016-01-13 17:31:56 +08:00
    我完全不同意 raysonx 的看法

    指针和整数是完全不同概念的东西,只是在 C 里面它刚好用一个特定长度的整数值表示而已(原因和硬件或者汇编的细节以及影响了 C 的设计的那些语言的细节有关)。

    指针的那些加加减减的操作符才是语法糖。正是这些操作符产生了它在逻辑上就是一个整数的假象。但是要明白,指针并不是整数,对它的这些加加减减代表的意义和遵循的规则并不完全和整数的那些一样。
    raysonx
        24
    raysonx  
       2016-01-13 17:51:02 +08:00
    @dorentus 你是在言的面上看的。於 CPU 什型有任何意,他只根你用指令的不同行不同的操作。程序的候,存都是需要地址作操作的。

    所加加所代表的意只是器面的西,器自把加法被指向型大小的倍。倍的是硬在目代中的。
    iyangyuan
        25
    iyangyuan  
       2016-01-13 17:52:10 +08:00 via iPhone
    因为是给聪明人看的,像我这种愚钝的人只能搞面向对象
    vanxining
        26
    vanxining  
       2016-01-13 18:21:37 +08:00 via Android
    @congeec 第二种是什么意思呢?没看明白。
    vanxining
        27
    vanxining  
       2016-01-13 18:25:36 +08:00 via Android
    哦,查了一下,原来是指向一个固定长度数组的指针。第一次看到。新技能 get√。
    Reficul
        28
    Reficul  
       2016-01-13 18:32:10 +08:00
    指针就是内存地址, C 语言的指针还是很容易理解的,只是容易在 debug 的时候抓狂
    b244183
        29
    b244183  
    OP
       2016-01-13 19:14:28 +08:00
    看了 K&R 的 5.12 Complicated Declarations
    基本搞懂了
    woai110120130
        30
    woai110120130  
       2016-01-14 07:29:26 +08:00 via Android
    我很费解 楼主为什么很费解
    louk78
        31
    louk78  
       2016-01-14 08:30:07 +08:00
    因为是给聪明人看的,像我这种愚钝的人只能搞面向对象
    msg7086
        32
    msg7086  
       2016-01-14 09:02:54 +08:00
    如果你觉得设计得不好,你应该 1972 年的时候就提出来。

    如果没有,那么说明你那时候 要么还没这水平去提意见,要么你还没出生。

    或者两者皆是。
    saeba1030
        33
    saeba1030  
       2016-01-14 10:41:39 +08:00
    对于指针来说,数据类型只是告诉指针应该以什么方式去存取内存里的数据,指针本身无所谓类型。
    cheng4741
        34
    cheng4741  
       2016-01-14 11:10:33 +08:00
    @msg7086 不同意你的观点,如果一个东西设计得不好,不一定能在当时就体现出来。很多东西都是随着时间的推移才发现原来设计的有问题。
    msg7086
        35
    msg7086  
       2016-01-14 11:24:23 +08:00
    @cheng4741 发现有问题就不能随便改了。

    你去看看 Python 3 。
    ma125125t
        36
    ma125125t  
       2016-01-14 11:36:05 +08:00
    @cheng4741 显然,设计的是有问题,不然哪有 OOP 什么事呢?
    chiuup
        37
    chiuup  
       2016-01-14 14:47:49 +08:00
    @saeba1030 准确地说,指针的数据类型是告诉编译器应该怎么样翻译成汇编码,指针本身是有类型的,并且这个类型在编译时很重要。
    chiuup
        38
    chiuup  
       2016-01-14 14:56:47 +08:00
    追溯到源头的话, C 是一帮对汇编代码十分精通的大牛设计的, C 是对汇编码最直接的一层抽象。如果你可以站在汇编程序员的角度来看 C 的这些设计的话,很多 C 的设计就很好理解了。比如说你提到指针算术,其实是对 lea 的一种特定用法的抽象。
    ahbcd112
        39
    ahbcd112  
       2016-01-14 15:08:58 +08:00
    很久很久以前。。。内存是非常非常贵的
    怎样节省怎么用。内存各种算
    内存的增长是指数增加的(比尔不是说过,个人电脑只要 32M 就够了!!某 N 年前电影,里面有一段,机器人能存储他看到的所有东西,因为他有一个非常非常大的硬盘。。。。 500MB )
    然而,开发费用。。。貌似没降多少吧。
    所以 OOP 各种发展,浪费点空间。减少开发、维护工作量。
    lilydjwg
        40
    lilydjwg  
       2016-01-14 15:17:26 +08:00
    @b244183 我曾经看到过有人讲 C 语言的指针和常量语法为什么会是现在这个样子。然而我早已不记得了……
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2720 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 09:47 PVG 17:47 LAX 02:47 JFK 05:47
    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