在C中有指针声明的约定吗?

问题描述:

声明用C指针,有2个(编辑:3)的变体:在C中有指针声明的约定吗?

方案A:
int* ptr;

方案B:
int *ptr;

变型C:
int * ptr;

  • 在A中,间接运算符已被附加到该类型。
  • 在B中,间接运算符已被预置到该变量。
  • 在C中,间接运算符在类型和变量之间*站立。

声明指针的方式因读取的文档类型而异。有些作者似乎对某些变体有偏好,有些则使用几种。

  • 我正确地认为在不同的变体之间的功能没有区别吗?
  • 如果是,那么在C中应该使用变体的约定吗?
+3

我不知道为什么人们投票关闭这个。这听起来像是一个合法的问题,但自1980年以来,我一直在黑客攻击C。 –

+1

@PeterRowell:这种微不足道的问题的唯一问题是,可以通过谷歌或任何其他搜索在网上找到答案。发动机在几秒钟内。而任何有关C的书籍都必须解释这一点。为什么不使用它们?不过,我没有投票结束。 –

+1

可能重复[在C++中声明指针时放置星号的位置是否重要?](http://*.com/questions/5449908/does-it-matter-where-i-place-the-asterisk-when -declaring-pointers -in-c) –

有绝对的功能

int* ptr; 

int *ptr; 

使用哪个是你没有任何区别,有多个冲突的编码款式可供选择。

+1

+1。就SO而言,这是正确的答案。没有区别,选择是你的。 –

+0

如果你想获得技术,使用'int * ptr;'也是等价的。只要星号介于类型名称和变量名称之间,空格就不重要。 – bta

+0

@DanFego:就编译器而言,这是正确的答案。使用一种表单或其他表单是有正当理由的,SO是讨论这些原因的绝佳地点。 –

只有当你打算在同一行声明多个相同类型的变量时,它才有意义。例如,如果你想多INT指针,你需要这样做:

int *a, *b, *c; 

文体不过,当你只声明一个变量,这是令人困惑。很多人喜欢看的类型,然后在变量名,类型应该是指向int的指针,不是int,所以他们宁愿:

int* a; 
int* b; 
int* c; 

这最终取决于你是否喜欢一个之上,其他。在专业编程C的20年中,我看到大约50%的人选择了另一种。

+0

这个(上述两个变体)是处理尴尬的星号关联规则的一种非常明显的方式。我避免写'int * a,b;','int a,* b;',和int * a,* b;'因为它们是注意力的征税,而不是因为我不知道它们每一个的含义。此外,编译所有启用的警告并保持代码警告清除有助于避免不希望使用整数作为指针,反之亦然。 –

+0

@ user1118321感谢您发布实际解决问题的少数答案之一:在同一行中声明多个变量。我严格反对将*与类型放在一起,因为它表明开发人员实际上并不了解语法。 – doug65536

你是对的,两者对编译器意味着完全一样的东西。这两条语句都会产生一个(int *)类型的变量。

至于哪一个是正确的:蠕虫可以! 这是一个辩论的话题。如果您为公司或OSS工作,最好遵循一种定义的编码风格。如果没有一个,我通常会选择LNT(不留痕迹)风格,以匹配这部分代码库中明显使用的任何风格。

可以说,对读者来说更容易理解。例如int* ptr;*接近int这更清楚地传达我们正在谈论的(int *)型...

在C,空白不除非它是需要单独的令牌关系。你的两个变体在语法上都是正确的。

变体1将指针操作符与类型相关联,这足够合理。对我来说,如果没有为什么Variant 2有道理,那就足够了。

变体2与C声明的构造方式一致。在C语法中,指针操作符属于声明器(即名称),而不是类型。在同一个声明中声明多个变量时,这很重要。它也有一些更深奥的案件。

因此,对我而言,变体2与C更加一致。但是任一变体都是有效的,两种变体都是常规的。

它们的含义与其他人所说的相同。虽然有一个陷阱等着你。考虑以下代码:

int* a, b; 

你可能会认为这宣告指针int。没有,否则。实际上aint*,但是bint。这是许多C程序员宁愿将*放在变量旁边而非类型的原因之一。当这样写的:

int *a, b; 

你就不太可能被误导,什么ab是。尽管如此,许多编码标准坚持认为每行只能声明一个变量,即,

int* a; 
int b; 

如果您遵循每行规则的一个变量,那么肯定没有混淆的余地。

T *a; 

是优选的C风格的方法来声明一个指向T如Kernighan的& Ritchie的本书中使用约C中所用

T* a; 

优选C++式的方式来一个声明指针T在Stroustrup关于C++的书中。

两个符号都是等效的。

+1

呼吁权威+1 ;-) –

东西别人没提的是

int *ptr; 

更符合语言的语法。

  • int *ptr;声明,它由:
    • 一个声明说明符int,随后
    • 一个声明符*ptr

(这实际上跳过一些步骤,但它横跨得到的基本思想。)

由于声明如下方式使用,这是什么意思是,*ptrint类型。由此得出ptr的类型为int*

有人可能会说,这使得它比

int* ptr; 

为同样的原因,

x = y+z; 

优于

x=y + z; 

当然你可以

int* ptr; 

并将其读为“ptrint*”类型。许多程序员都是这么做的,相处得很好(它往往是C++的首选风格)。编译器并不在乎你用哪种方式来做,而且任何阅读代码的人都不应该无法理解它。

但两者间距让你选择,你需要了解什么int *ptr;的真正含义,所以,当你看到

int *ptr, i; 

在别人的代码(如你不可避免地会),你会立即明白ptr是一个指针和i是一个int。

如果您正在与项目中的其他程序员一起工作,那么您应该遵循编码标准中的任何现有约定,或者如果没有,那么代码已经编写的方式。我个人更喜欢int *ptr;int* ptr;,但使用这两种风格的混合比使用任何一种风格要差得多。

C声明基于表达式的类型,而不是对象。

如果你有一个指向名为piint,你要访问的整数值,它指向的,你必须取消引用指针,如:

x = *pi; 
printf("%d", *pi); 
*pi = 1 + 2; 

等。该类型的表达*pi的是int:因此,声明应为

int *pi; 

现在让我们假设你有一个指针数组来char;去任何字符,则需要第一个下标到阵列,然后解除引用的结果:

c = *pc[i]; 
if (*pc[j] == 'a') {...} 

等同样,表达*pc[i]char的类型,所以声明读取,

char *pc[N]; 

两个*pi*pc[N]被称为说明符,并指定不被类型指定给定的附加类型的信息。 IOW,pc的数组内容和指针被指定为声明器的一部分,而char -ness由类型说明符给出。

至于问题,其中的风格是适当 ...

一个都不是“正确的”,但我(和许多其他的C程序员)喜欢写T *p而不是T* p,因为它更接近地反映了语言语法(*是声明的一部分),它有助于在声明多个项目时避免混淆。我见过太多人写作的例子T* a, b;和期待b是一个指针。

对这种批评的常见反应是“每行不要声明多个项目”。我对这种回应的回应是“正确编写你的申报人,你不会有任何问题”。

有许多C++程序员,谁喜欢T* p风格之间的不同学派的,我不得不说,有少数病例(仅限于C++)那里可以使代码更易读。

但是,只适用于指向T的简单指针:当您开始处理指针数组,指向数组的指针,指向函数的指针或指向函数指针数组的指针时,范例会迅速崩溃。我的意思是,写什么类似

T* (*(*p)[N])(); // p is a pointer to an array of pointers to functions 
       // returning pointers to T. 

只是表示困惑的思想。尽管如此,如果你真的真的真的觉得你必须遵循T* p范式,你总是可以创造出一系列的类型定义的:

编辑

让我们再试一次:

typedef T* TPtr;       // pointer to T 
typedef TPtr TPtrFunc();     // function returning pointer to T 
typedef TPtrFunc* TPtrFuncPtr;    // pointer to function returning 
              // pointer to T 
typedef TPtrFuncPtr TPtrFuncPtrArray[N]; // N-element array of pointer to function 
              // returning pointer to T 

TPtrFuncPtrArray* p; 

对于上帝的爱,不要这样做。