Chinaunix

标题: [低水平帖]定义和声明时,星号(*)是靠着类型还是靠着变量 [打印本页]

作者: txdgtwpv    时间: 2011-08-23 12:08
标题: [低水平帖]定义和声明时,星号(*)是靠着类型还是靠着变量
发个无聊的帖子,关于*,&的摆放位置的{:3_189:}


举个例子声明一个字符指针str,是把星号放在什么地方好呢

char* str; 还是 char *str;

第一种的好处据说是:char*是用*修饰类型,表示是这种类型的指针

第二种的好处据说是:如果用第一种,char* a,b;就容易让人混淆。

大家来谈谈看法吧


PS:俺觉得俺的问题挺好的,应该不会导致C/C++版块越来越差
作者: pandaiam    时间: 2011-08-23 12:29
选3
作者: 三月廿七    时间: 2011-08-23 12:48
我喜欢1, 因为看上去更像复合类型
作者: Fatihyang    时间: 2011-08-23 13:44
N多代码 都是  char *str
建议楼主 多看看别人优秀的代码
作者: nth2say    时间: 2011-08-23 13:57
一般用 char *str;
作者: 鸡丝拌面    时间: 2011-08-23 15:06
选3
pandaiam 发表于 2011-08-23 12:29



    不偏不倚,中庸之道也!
作者: txdgtwpv    时间: 2011-08-23 15:26
N多代码 都是  char *str
建议楼主 多看看别人优秀的代码
Fatihyang 发表于 2011-08-23 13:44



    我原来也是用 char *str;

就是最近看了一些nb的代码之后才开始怀疑的。。。
作者: ilwmin    时间: 2011-08-23 15:45
果断第二个,习惯问题
作者: ezioma    时间: 2011-08-23 15:48
低端coder表示选2
作者: 幻の上帝    时间: 2011-08-23 16:36
需要照顾脑残infix语法无聊写法么。
char *a,b; //!< 插个后缀注释都麻烦。
作者: ZSMDEV    时间: 2011-08-23 16:39
靠近变量
作者: pmerofc    时间: 2011-08-24 00:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: txdgtwpv    时间: 2011-08-24 12:42
{:3_191:}
作者: 幻の上帝    时间: 2011-08-24 13:11
*的语义是修饰类型无误,不过语法上是修饰对象。
作者: bigxu    时间: 2011-08-25 09:37
声明时 char   *   var; 用时 *var
作者: pmerofc    时间: 2011-08-25 10:14
提示: 作者被禁止或删除 内容自动屏蔽
作者: jiayanfu    时间: 2011-08-25 10:22
果然没跟大家错开。。。{:2_168:} 第2种
作者: A13433758072    时间: 2011-08-25 17:57
第二个
作者: captivated    时间: 2011-08-26 08:12
回复 1# txdgtwpv


    现在我喜欢用第一个。这是《C++ Templates》中建议用的风格。这种风格非常明确地说明了:类型 char* 和对象 var 是分离的。《C++ Primer》中也明确说明了,指针、引用、数组是复合类型。不过貌似《C++ Primer》中示例代码也是用第二种(忘记了)?

    第二个,纯粹的C程序员喜欢吧... 《The C Programming Language》里面用的是第二种。

    原来我喜欢第二种风格的说... 现在越发喜欢第一种而讨厌第二种。嗯,类型就是类型,变量就是变量,干嘛乱写?
    比如C++定义引用的用法:
    int a;
    int& b = a;
    我觉得很少有人喜欢这样写引用:
    int &b = a;

    char *a, b; // 拿这种说事的人估计会喜欢谭浩强老师书里的代码风格吧... 很少有人喜欢把指针和单纯的类型放在一起声明。一般来说声明都是分开的单行,如果不是单行,那同一行里面至少应该声明同样的类型吧。

    这个不说... 《C++ Templates》还建议这样的风格呢:
    int const var;
    int const* const p_var;
    因为...把const放在类型后面有益于维护typedef的语义...

    最后... 其实都是扯淡的... 不过现在我还是喜欢第一种(至于第3第4嘛...表示很纠结)... 这是为什么呢...
作者: chinesedragon    时间: 2011-08-26 08:17
我觉得是char* str;好。。。
作者: ckf513728912    时间: 2011-08-26 10:15
我喜欢第二种
作者: pmerofc    时间: 2011-08-26 10:44
提示: 作者被禁止或删除 内容自动屏蔽
作者: captivated    时间: 2011-08-26 11:20
回复 22# pmerofc


    非要在一行定义两个指针么。凡定义指针分行写行不。何况,指针的使用哲学不是“定义时即正确地初始化”吗?

    int*  a;  // 这是个野指针。

    严格地说,要么:
    int* p = NULL;
    要么:
    int* p = (int*)malloc(100 * sizeof(int));

    语义上,“*”是修饰类型的。指针是复合类型,就是说,你不可能定义一个类型无关的指针。引用、数组也是一样的。《C++ Primer》里面特别指出的。
    * p; // 啊,这样是定义一个类型无关的指针吗?

    定义指针的时候,你必须指明,这个指针是什么类型的指针(或者说指向什么类型):
    int* p;

    别说:
    void* p;
    是类型无关的。void* 表示指针是"void"类型。

    所以说:
    TYPE*  p; // 这种方式明确地,区分了,变量,和类型。它表示:变量p是TYPE*类型。对于类属/泛型编程来说,类型和变量的区分很重要。类型是类型,对象是对象。
    而
    TYPE   *p; // 这表示什么呢?表示变量*p是TYPE类型? no,它的语义仍然是:变量p是TYPE*类型。
作者: pmerofc    时间: 2011-08-26 11:41
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-08-26 11:42
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-08-26 11:43
提示: 作者被禁止或删除 内容自动屏蔽
作者: captivated    时间: 2011-08-26 12:06
回复 26# pmerofc


    这种就没办法了... 哈哈。

    啊,要是按照类型修饰的说法,应该是这样写:

    int[3]* pary;   // 指向数组的指针。
    int*[] aryp;     // 指针数组

    可惜C没有这样的语法,呵呵
作者: captivated    时间: 2011-08-26 12:10
回复 26# pmerofc


    比如C中声明数组非要这样写:
    int ary[];

    Java、C#之类的,都改成这种写法了(其目的也是在语法风格上强调类型和变量的分离):
    int[] ary;
作者: 三月廿七    时间: 2011-08-26 12:13
本帖最后由 三月廿七 于 2011-08-26 12:14 编辑
回复  pmerofc


    比如C中声明数组非要这样写:
    int ary[];

    Java、C#之类的,都改成这种 ...
captivated 发表于 2011-08-26 12:10

原来我自己的感觉就是权威...
作者: pmerofc    时间: 2011-08-26 12:19
提示: 作者被禁止或删除 内容自动屏蔽
作者: 幻の上帝    时间: 2011-08-26 16:54
“修饰类型” 这个词应该怎样理解?
pmerofc 发表于 2011-08-25 10:14



先修正我之前的说法。
语义和语法上都可以是修饰类型的,也可以是修饰对象。
ISO C对对象声明和类型名分别做了规定。*在声明符中修饰对象,在类型名中修饰类型。这是纯粹直接的按语法分类的结果。在此之上,对应的语义也可以修饰对象或类型。
不过如果跳出C语言之外,这样未免过于冗余了。实际上指针声明符的作参与决定对象类型,因此即使是修饰对象的*,同时也在修饰类型,即使没有在语法上直接表示出来。
作者: 幻の上帝    时间: 2011-08-26 16:55
回复  captivated


    实在嘴笨,我举个例子吧
  
   int   (*p)[3];

    你怎么写
pmerofc 发表于 2011-08-26 11:43

typedef。
作者: 幻の上帝    时间: 2011-08-26 16:57
本帖最后由 幻の上帝 于 2011-08-26 17:12 编辑
观念上,把类型和变量分开也许是一种进步
   可惜C目前还不接受这样的语法
   int   (*)[3]    ...
pmerofc 发表于 2011-08-26 12:19

我觉得不太可能会有。这种中缀表达式的滥用是C/C++的习惯乃至传统,连Java也不能幸免(数组声明仍然兼容这种风格)。
另外,起码typedef给用户一种避免此类用法的自由,所以一些可读性差的写法也并不是无可避免的,对分离类型和对象的声明语法的需求并没有很迫切。
这种语法实际上确实较简单也较容易实现,但看来对于早已经实现了现有声明语法的编译器厂商而言没多大吸引力

题外话,这种传统应该有些涉及到语言设计的哲学上了……
对于routine,C语言为什么只提供易于使用调用栈实现的function,而不是coroutine?为什么不给用户显式清理continuation/stack frame的接口?
作者: pmerofc    时间: 2011-08-26 22:54
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-08-26 22:57
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-08-26 23:02
提示: 作者被禁止或删除 内容自动屏蔽
作者: 幻の上帝    时间: 2011-08-27 01:34
C的确有不少事先没考虑周全的地方。不过我觉得C的那些缺点都不讨厌,也有办法避免
pmerofc 发表于 2011-08-26 23:02


用起来是不讨厌,但要深究原因的话会很郁闷,总是会有一种自己变成那种无意义的语言哲学家的错觉……还有一种问题明明存在却拿它没办法的无力感。
作者: tarside    时间: 2011-08-27 19:47
回复  txdgtwpv


    现在我喜欢用第一个。这是《C++ Templates》中建议用的风格。这种风格非常明确地 ...
captivated 发表于 2011-08-26 08:12



    我支持这个。
作者: 林生2010    时间: 2011-08-27 23:58
以前用第二种,后来改用第一种了,把类型和变量分开看着舒服些。  PS:    C++都升级了, C也该升级了吧  现有的C89、C99都显得有些古老了。
作者: 放纵思想    时间: 2011-08-28 10:56
第3个和第5个不是一样的吗?
作者: wwjxjtu    时间: 2011-08-28 14:27

作者: txdgtwpv    时间: 2011-08-29 16:34
第3个和第5个不是一样的吗?
放纵思想 发表于 2011-08-28 10:56



    第五个我写的

  1. char             *                 str;
复制代码
格式被改掉了
作者: cjxgm    时间: 2011-08-30 20:35
既然第一个会有 char* a,b; 的错误,第二个不符合“类型与变量分离”,那就干脆第三个
作者: silverzhaojr    时间: 2011-08-30 23:55
用第一个char* str,当初在Thinking in C++上看到这样建议的,然后就一直这样用了……
作者: yanpengzhai    时间: 2011-08-31 15:38
比较喜欢使用第二种,可以直观的看到声明的类型是指针滴。。。
作者: 嘟猫猫    时间: 2011-09-04 16:39
一般用 char *str
作者: supermegaboy    时间: 2011-09-04 19:04
无论靠类型还是靠标识符都有缺点,更好的做法是靠类型,但不同类型的对象声明放在不同行,例如:

char a;
char* p;
int* pi;
作者: pmerofc    时间: 2011-09-04 19:06
提示: 作者被禁止或删除 内容自动屏蔽
作者: txdgtwpv    时间: 2011-09-06 12:16
唉,还是相信群众,继续用第二种
作者: chiyiangel    时间: 2011-09-06 12:44
3和5  有区别么{:3_201:}
作者: supermegaboy    时间: 2011-09-06 20:02
回复 48# pmerofc


    也许你以为我会说同类变量并排声明,但我推荐的是一行只声明一个变量!例如:
  1. char a;
  2. char b;
  3. char* p;
  4. char* q;
  5. double k;
  6. vector<int> j;
复制代码
在过去数年的某一天,当我看见有人这样排列变量时,它的整齐与清晰让我大开眼界,我终于可以长吁一口气:对!这就是我想要的!
作者: ChiyuT    时间: 2011-09-06 20:24
回复  supermegaboy


   要是有两个char*类型的变量需要定义呢?
pmerofc 发表于 2011-09-04 19:06


一直都是用gcc的扩展,
  1. typeof(char *)  x, y;
复制代码

作者: pmerofc    时间: 2011-09-07 00:16
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-09-07 00:17
提示: 作者被禁止或删除 内容自动屏蔽
作者: txdgtwpv    时间: 2011-09-07 13:11
一直都是用gcc的扩展,
ChiyuT 发表于 2011-09-06 20:24



    真是好办法
作者: silverzhaojr    时间: 2011-09-08 00:19
一直都是用gcc的扩展,
ChiyuT 发表于 2011-09-06 20:24


这个用法看起来不错呀,试试去~
作者: xiaonanln    时间: 2011-09-08 09:02
写成char *p,并且理解成*p是char类型,能避免你写出
char* a, b;这样的错误代码
作者: kycgjy    时间: 2011-09-10 11:29
我选2
作者: victor0423    时间: 2011-09-10 22:53
目前基本是2
作者: huxk    时间: 2011-09-13 13:15
蛋蛋
作者: chenbin200818    时间: 2011-09-13 16:36
好习惯是很重要的
必然是第一个
作者: supermegaboy    时间: 2011-09-15 18:37
回复 53# pmerofc

好好试一试,你会感受到那无与伦比的清晰的。
作者: asuka2001    时间: 2011-09-15 18:56
没有实质上的区别吧? 一般来说大家都看得懂不是么!

感觉可读性也并没有本质上的提升。。。。

又想起自己当年纠结这两种写法了

if (condition) {
      ......
}



if (condition)
{
      ......
}
作者: pmerofc    时间: 2011-09-15 23:31
提示: 作者被禁止或删除 内容自动屏蔽
作者: xxfihm    时间: 2011-09-15 23:43
支持:
char* x;
的方式    理由同上
作者: supermegaboy    时间: 2011-09-16 22:50
回复 64# pmerofc


    我第一次见这种方式的时候那家伙定义了十几个变量。
作者: 三月廿七    时间: 2011-09-16 23:03
int x, y, z;
int vy, vy, vz;
int ax, ay, az;

int x;
int y;
int z;
int vx;
int vy;
int vz;
int ax;
int ay;
int az;

我觉得第一种要紧凑一点,
不过, 我现在喜欢给每一个结构体变量写一注释, 不得已选第二个
作者: 毛xx总理    时间: 2011-09-17 09:29
int x, y, z;
int vy, vy, vz;
int ax, ay, az;

int x;
int y;
int z;
int vx;
int vy;
int vz; ...
三月廿七 发表于 2011-09-16 23:03



    同意。
作者: 毛xx总理    时间: 2011-09-17 09:30
回复  pmerofc


    也许你以为我会说同类变量并排声明,但我推荐的是一行只声明一个变量!例如:在过 ...
supermegaboy 发表于 2011-09-06 20:02



    有同感。
作者: pmerofc    时间: 2011-09-18 10:23
提示: 作者被禁止或删除 内容自动屏蔽
作者: blairzhong    时间: 2011-09-18 14:46
我选2, 理由:习惯
作者: littledick    时间: 2011-09-21 16:28
习惯声明一个“字符指针类型”变量,而不是 声明一个变量“它引用的是一个字符”。
作者: Oldnightowl    时间: 2011-09-27 17:04
当然是第一个了!
作者: shuimu159951    时间: 2011-09-28 00:05
不知不觉发现我习惯用的是第二种了
作者: KBTiller    时间: 2011-09-28 09:58
星号(*)本身应该是变量类型的一部分

int  (*a)[3];
会发现,*靠着int是不可能的
作者: littledick    时间: 2011-09-30 11:20
回复  captivated


    实在嘴笨,我举个例子吧
  
   int   (*p)[3];

    你怎么写
pmerofc 发表于 2011-08-26 11:43



    C++里声明有3个int指针变量的数组用 int* p[3]没问题的。
作者: pmerofc    时间: 2011-09-30 15:32
提示: 作者被禁止或删除 内容自动屏蔽
作者: littledick    时间: 2011-09-30 17:03
回复  littledick


    我的那个例子和你说的这个明显不是一回事
pmerofc 发表于 2011-09-30 15:32



    如果你声明的时候不写注释,我真的会先这样理解 = =。
作者: littledick    时间: 2011-09-30 17:07
退一步说,你在对指针变量做强制类型转换,比如子类指针转基类时是用:
(SUPPER_TYPE*)pChildPointer
还是用
(SUPPER_TYPE)*pChildPointer
作者: pmerofc    时间: 2011-09-30 17:08
提示: 作者被禁止或删除 内容自动屏蔽
作者: A13433758072    时间: 2011-10-01 23:44
1   容易看
作者: captivated    时间: 2011-10-06 05:14
回复 76# littledick


    int* p[3]; 和int (*p)[3]; 是不同的,完全不是一回事。你C指针没学好。
作者: captivated    时间: 2011-10-06 05:18
回复 75# KBTiller


    这是C在语法上的缺陷。 指针是数据类型,应该算到类型系统里去。

   如果是“正确”的语法,我觉得应该是这样的:

   int*[] p;          // int* p[];  p是一个指针数组
     int[3]* p;         // int (*p)[3]; p是一个指向数组的指针
作者: kzl0629    时间: 2011-10-18 15:03
我选1,
一般都是定义一个变量占一行的
如:
int* a;
int *b;
作者: shanehan    时间: 2011-10-20 14:04
记得google的代码风格上要求char *c;
作者: zffjh2021    时间: 2011-10-21 15:02
2
作者: irwin_star    时间: 2011-10-22 23:22
一般都是建议 char *a, 防止 char* a,b 这样的错误。
但是我一般还是喜欢char* a , 但是注意一下不犯那个错误就行呗。
作者: walleeee    时间: 2012-02-14 01:52
对于这个,我曾经的写法是char* c;
后来改成了char *c;

char* c的写法多见于书籍中,特别是我最开始读的那几本书,所以开始就这样写了,但是大多的开源代码中倾向char *c这种,我也纠结过。后来某高人点化,我毅然选择了char *c;

其实两者之间选择的一个困难在于该不该把类型指针当作一个新类型,即,该不该把char*当作一个类型。但是char *c带来的好处远远比char* c带来的好处多,所以我选了后者。

关于这个问题,还可以引申到引用&的用法。比如char& c和char &c这种。

关于第二个char *c1, c2这种我个人原则是每条声明语句只声明一个东西,比如此句就该写成
char *c1=0;
char c2=0;
这种。
作者: walleeee    时间: 2012-02-14 01:54
ps.
而那种char * c的写法在书籍中少见,但是在代码中还是存在较多。

总之,不管怎么写,一定要贯彻代码始终,不要一会这样一会那样,选一个就行。
作者: walleeee    时间: 2012-02-15 00:02
回复 80# pmerofc


    还是说c++的吧,免得旁生枝节。你写'看来你完全不懂c++的类型系统'就好
作者: walleeee    时间: 2012-02-15 00:06
回复 39# 林生2010


    c11已经出了。不过只要大家一致,各种编译器能对一个标准支持好,哪个版本都无所谓。不然很蛋疼的,看看现在的c++11你就懂了。
作者: 林生2010    时间: 2012-02-21 23:34
回复 91# walleeee


    编译器是核心,代码再好,编译器不给力,也是空谈。
作者: walleeee    时间: 2012-02-21 23:36
回复 92# 林生2010


    你想表达什么 我没看明白
作者: 林生2010    时间: 2012-02-21 23:44
回复 93# walleeee


。。。。。。  我的意思是编译器是核心
作者: walleeee    时间: 2012-02-21 23:47
回复 94# 林生2010


    哦
作者: digdeep126    时间: 2012-02-25 17:17
在定义指针变量时: char  *pc;
在声明函数是: void*  fun();
作者: hbmhalley    时间: 2012-02-26 00:01
记得<C缺陷>里面说那个倒霉void(*signal(int,void(*)(int)))(int)的时候大概是这么说的:
首先 外面是 void(*xxx)(int),即 (*xxx)(int) 返回类型为void,(*xxx)为该函数的`函数名',即:xxx为指向此类型函数的指针,解引用后是个函数
然后 xxx是signal(int,void(*)(int)),也就是说,signal()是一个函数,返回类型是xxx的类型,即上面说的[指向void()(int)类型函数的指针]
里面的void(*)(int)就不解释了

也就是说 void 是最终的结果,导致这个结果的是 (*signal(int,void(*)(int)))(int)这样一个函数 而这样一个函数本身也是通过signal()`计算'得到的

按照这样的说法,char * p 意思其实是 (*p) 是个char , char是p解引用得到的,p 理所当然就是个指向char的指针

至于 char * p [] 与 char (*p) [] 的问题,我的理解是:`[]' 优先级高于 '*' (这应该没什么问题) ,于是 `char * p []' 意思就是 (*(p[0]))是个char ;而 `char (*p)[]' 的意思是 ((*p)[0]) 是个 char

这样看来 还是 char *p 比较符合类型定义的本意,甚至可以写成 char (*p)
作者: lilinly225    时间: 2012-04-29 17:48
我的习惯;当用typedef的时候,靠近char;  多个变量同时定义的时候,靠近每个变量; 单个变量则无所谓了
作者: lu18887    时间: 2012-05-01 13:55
Fatihyang 发表于 2011-08-23 13:44
N多代码 都是  char *str
建议楼主 多看看别人优秀的代码


此话不妥,优秀的代码里,有些是习惯,有些是必须!
作者: wolf5729    时间: 2012-05-06 09:17
我的习惯就是使用第2种风格。

------------------------------------
欢迎光临我的博客:www.danoking.com [DNK的生涯|IT人的故事]




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2