V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zxCoder
V2EX  ›  问与答

C++指针的*号位置为什么这么别扭啊

  •  
  •   zxCoder · 2020-10-15 17:09:47 +08:00 · 2777 次点击
    这是一个创建于 1533 天前的主题,其中的信息可能已经有所发展或是发生改变。
    int *fun(){}
    

    这是返回一个 int 型指针,咋不写成

    int* fun(){}
    

    我的理解是为了强调 int*不是一个类型,而*函数名()就表示返回一个“所声明的返回类型”的指针类型。

    Clion 自动格式化也会格式化成第一种

    第 1 条附言  ·  2020-10-15 20:16:58 +08:00
    好像也没有什么太好的解释,我觉得就是设计问题,怎么形容呢,就是有点像“撒了第一个谎,就要用无数个谎来圆第一个谎” 哈哈哈

    不过我觉得每种语言都或多或少有一些写法上的毛病,习惯就好,不引战不引战
    26 条回复    2021-11-15 20:40:05 +08:00
    BrettD
        1
    BrettD  
       2020-10-15 19:15:27 +08:00 via iPhone
    因为 int* a, b;的意思是 int *a, b
    geelaw
        2
    geelaw  
       2020-10-15 19:18:20 +08:00   ❤️ 2
    int * 当然是类型。正确的原因如 #1,因为 * 是和标识符结合,而不是和类型名字结合。

    int *a, b; 的意思是 int *a; int b; 如果写成 int* a, b; 则容易误以为意思是 int *a; int *b; 所以 * 永远靠近标识符。为了一致性,在声明返回类型的时候也让 * 靠近标识符(即函数的名字)。
    kokutou
        3
    kokutou  
       2020-10-15 19:18:43 +08:00   ❤️ 1
    复制粘贴的:

    以下文字摘自<高质量 C++编程指南>:

    修饰符 * 和 & 应该靠近数据类型还是该靠近变量名,是个有争议的活题。

    若将修饰符 * 靠近数据类型,例如:int* x; 从语义上讲此写法比较直观,即 x 是 int 类型的指针。

    上述写法的弊端是容易引起误解,例如:int* x, y; 此处 y 容易被误解为指针变量。虽然将 x 和 y 分行定义可以避免误解,但并不是人人都愿意这样做。
    letking
        4
    letking  
       2020-10-15 19:27:35 +08:00
    不管怎么解释,这种写法确实别扭。
    zxCoder
        5
    zxCoder  
    OP
       2020-10-15 19:43:01 +08:00
    @kokutou 我感觉就是设计问题,但是已经太难改了,类似于 int* x,y 在很多语言应该都是表示两个 int* 变量,而 c++非要表示一个 int*,一个 int,然后说引起误解。。。。
    当然也可能是我先学了其他语言,先入为主
    zxCoder
        6
    zxCoder  
    OP
       2020-10-15 19:44:07 +08:00
    @BrettD
    @geelaw
    你们觉得这是最初的设计问题吗?我觉得在大多数现代语言中,类似于 int* x,y 的表达应该都是表示两个 int*类型的,感觉更容易理解。
    zxCoder
        7
    zxCoder  
    OP
       2020-10-15 19:45:04 +08:00
    @letking 写习惯了应该还好,像我这种半吊子就容易看错代码,理解半天哈哈哈
    AlohaV2
        8
    AlohaV2  
       2020-10-15 19:45:47 +08:00
    我一般就写 T* SomeWhatFunction()
    参考 https://google.github.io/styleguide/cppguide.html#Pointer_and_Reference_Expressions
    我觉得是保持整个项目的风格一致即可,没那么多条条框框
    secondwtq
        9
    secondwtq  
       2020-10-15 19:47:23 +08:00
    这不是 C 的问题么 ... 我 C++ 虽然垃圾,但是也要面子的啊
    嘛,C++ 加了一个引用 ... 在这方面很相似

    我觉得这样设计一个可能的动机是保持标识符的定义与使用一致,也就是说定义的时候用 *a,使用的时候也用 *a,*a 这个表达式的类型就是 int 。
    Mutoo
        10
    Mutoo  
       2020-10-15 19:51:49 +08:00
    https://clang.llvm.org/docs/ClangFormatStyleOptions.html

    # Force pointers to the type for C++.
    DerivePointerAlignment: false
    PointerAlignment: Left
    dandycheung
        11
    dandycheung  
       2020-10-15 19:52:22 +08:00 via iPhone
    @zxCoder 跟设计关系不大,保证自己不用指针类型同时定义多个变量的前提下,我每次都会把星号挨住类型,别人的代码的话,我也要强制改过来,除非是独立的源文件,不需要大动的。
    secondwtq
        12
    secondwtq  
       2020-10-15 19:58:51 +08:00
    @zxCoder #6 C 不是“现代语言”,C++ 想要“现代”也“现代”不起来了。
    其实现在 C++ 和 Rust 这种零开销抽象语言里面一堆智能指针,感觉已经没啥必要给指针专门设计语法了。
    rrfeng
        13
    rrfeng  
       2020-10-15 20:10:40 +08:00
    一个声明语句里同时声明两个不同类型的变量,其他语言没有这么写的。就是设计的别扭而已……
    elfive
        14
    elfive  
       2020-10-15 20:12:37 +08:00 via iPhone
    因为#1 和#2 的原因,所以我总是在*两边加上一个空格,这样就写成了:
    int * a, b;
    int * foo(){ return bar; }

    这样比较居中的话我个人觉得没有侧重,多数情况下都还算好理解。
    lxk11153
        15
    lxk11153  
       2020-10-15 20:27:09 +08:00
    哈哈,联想到 Java
    String[] a={};
    String b[]={};
    // ----
    String[] c={}, d={};
    // ----
    String e[]={}, f[]={}, g="";
    blless
        16
    blless  
       2020-10-15 20:29:47 +08:00 via Android
    虽然一开始觉得 go 别扭 不过感觉 go 就没有这方面困扰 反正类型都后置
    Akiyu
        17
    Akiyu  
       2020-10-15 20:35:04 +08:00
    int *a;
    除了楼上所说的以外. 从类型对称上来说 int 和 *a 分开. 左右对称. 意为 *a 是 int 类型. 而 a 只是个指针.
    从这方面来说. 也可以辨别 * 应处的位置.
    kokutou
        18
    kokutou  
       2020-10-15 20:45:27 +08:00
    @zxCoder #5
    c++要兼容 c
    c 是多久以前发明的...

    这包袱甩不掉
    sillydaddy
        19
    sillydaddy  
       2020-10-15 21:14:37 +08:00 via Android
    @Akiyu 同意
    楼主可以从 17 楼的解释来理解。
    int *foo()的意思是*foo()的类型是 int,这样 foo 函数返回类型自然就是一个指向 int 的指针,用*对指针取值才得到 int 类型。
    sillydaddy
        20
    sillydaddy  
       2020-10-15 21:20:19 +08:00 via Android
    @sillydaddy 也就是说,你既可以把*看作是指针的符号,同时也可以看作是对指针取值的操作符。
    这样的话,int *a 的含义,可以理解为 a 是 int *,也可以理解为,对 a 这个变量用*取值后,得到的值类型为 int,那 a 自然就是 int 类型的指针啊,因为只有对 int 型的指针取值,得到的才是 int 型的值啊。
    crclz
        21
    crclz  
       2020-10-15 22:37:56 +08:00
    我 vscode c++ 格式化用的 Chromium 配置,
    它会做出以下的格式化:
    int* a;
    int *c, *d;
    by73
        22
    by73  
       2020-10-16 00:23:25 +08:00   ❤️ 1
    “成也兼容 C,败也兼容 C”
    levelworm
        23
    levelworm  
       2020-10-16 01:13:32 +08:00 via Android
    @zxCoder 我觉得这种代码不写即可,每个变量占一行。
    black11black
        24
    black11black  
       2020-10-16 01:16:47 +08:00
    月经问题
    msg7086
        25
    msg7086  
       2020-10-16 04:30:10 +08:00
    现代语言?现代语言可以用现代技术啊?
    智能指针,多好。
    很快 new 就要过气并移除了,以后写代码都是智能指针生成对象了。
    然后传指针也可以改用传引用。
    只有和古典代码交互的时候才需要裸传指针地址了。
    JackalZhao
        26
    JackalZhao  
       2021-11-15 20:40:05 +08:00
    * 后置我也看着难受,我猜 C 语言这个设计是为了兼容这样的语法:

    ```
    int *pointers[10]; /* Declares an array of pointers */
    int (*pointer)[10]; /* Declares a pointer to an array of 10 elements */
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3254 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 12:50 · PVG 20:50 · LAX 04:50 · JFK 07:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.