在C中,声明指针的正确语法是什么?

我依稀记得在回答另一个问题之前看到这个,但search没有得出答案。

我不记得什么是正确的方式来声明variables是指针。 是吗:

Type* instance; 

要么:

 Type *instance; 

虽然我知道在大多数情况下都会编译,但我相信有一些例子很有意义,可能与在同一行中声明多个相同types的variables有关,所以比另一个更有意义。

这只是一个你喜欢阅读的问题。

有人这样说的原因是:

 Type *instance; 

是因为它说只有实例是一个指针。 因为如果你有一个variables列表:

 int* a, b, c; 

只有一个是一个指针,所以它更容易

 int *a, b, c, *d; 

a和d都是指针。 它实际上没有区别,只是可读性。

其他人喜欢*旁边的types,因为(除其他原因之外),他们认为它是一个“指向一个整数”,并认为*属于types,而不是variables。

我个人总是这样做

 Type *instance; 

但这真的取决于你,以及你的公司/学校代码风格的指导方针。

那两个是一样的 但是,如果你做了多个声明,前者可以陷害你。

int* pi, j;

声明一个int指针( pi )和一个int( j )。

这是C语法的一个意外,你可以用它来写。 然而,它总是被parsing为

 Type (*pointer); 

也就是说, *总是绑定到声明符,而不是types说明符。 如果你写了

 Type* pointer1, pointer2; 

它会被parsing为

 Type (*pointer1), pointer2; 

所以只有pointer1会被声明为一个指针types。

C遵循“声明模仿使用”的范式; 声明的结构应尽可能模仿代码中使用的等同expression方式。 例如,如果您有一个指向int int的指针数组,并且您想要检索数组中的第i个元素所指向的整数值,则可以下标该数组并将其解除引用,结果写为*arr[i] (parsing为*(arr[i]) )。 expression式 *arr[i]int ,所以arr的声明被写为

 int *arr[N]; 

哪种方式是正确的 ? 取决于你问的问题。 像我这样的老C屁就更喜欢T *p因为它反映了语法中实际发生的事情。 许多C ++程序员都喜欢T* p因为它强调T* p的types,在许多情况下(自己编写了容器types,我可以看到这一点,虽然对我仍然感觉不对),感觉更自然。

如果你想声明多个指针,你可以明确地声明它们,比如:

 T *p1, *p2, *p3; 

或者你可以创build一个typedef:

 typedef T *tptr; tptr p1, p2, p3; 

尽pipe我个人不推荐它。 如果你不小心的话,隐藏在typedef后面的东西的指针会咬你。

这两个是完全一样的。

但是,为了声明多个variables,如下所示:

 int * p1, p2; 

其中p1是指向int的types指针,但是p2的types是int。 如果你想把p2声明为int指针,你必须写:

 int *p1, *p2; 

我更喜欢以下风格:

 Type *pointer; 

为什么? 因为它符合语言的创造者所设定的心态:

“variables声明的语法模仿variables可能出现的expression式的语法。”

(由Brian W. Kernighan和Dennis M. Ritchie 编写的C编程语言 ,第94页,版本)

使用任何语言编写FORTRAN都很容易,但是您总是应该使用[编程语言X]编写[编程语言X]。

奇怪的是,这个规则不适用,如果types是在C ++ 0x推导。

 int a; decltype(&a) i, j; 

我和j都是int *。

所有这些都将编译,是合法的,是相当的:

 Type* instance; Type * instance; Type *instance; 

select一个风格,并保持一致。

作为一个方面说明,我认为这有助于理解C声明语法背后的动机,这是为了模仿如何使用variables。 下面是一些例子:

  • char *x意味着如果你做*x ,你会得到一个char
  • int f(int x)意味着如果你做例如f(0) ,你会得到一个int
  • const char *foo[3]意味着如果你做eg *foo[0] (与*(foo[0]) ),你会得到一个const char 。 这意味着foo必须是指向const char的数组(在这种情况下,大小为3)。
  • unsigned int (*foo)[3]意味着如果你做eg (*foo)[0] ,你得到一个unsigned int 。 这意味着foo必须是指向unsigned int (在这种情况下,大小为3)的数组的指针。

松散地说,一般的语法是[what you get] [how you get it] 。 诀窍是,这可以扩展到[what you get] [how you get it], [how you get it], ...一次宣布多个事物。 因此,以下三个声明 –

 int *p; int f(int x); int a[3]; 

– 可以合并成一行,如下所示(是的,这甚至适用于函数声明,在这方面它们并不特别):

 int *p, f(int x), a[3];