为什么反引用操作符(*)也用来声明一个指针?
我不确定这是否是一个适当的编程问题,但这一直是困扰着我的东西,我想知道我是否是唯一的问题。
最初学习C ++时,我理解了引用的概念,但是指针让我感到困惑。 你为什么问? 由于你如何声明一个指针。
考虑以下:
void foo(int* bar) { } int main() { int x = 5; int* y = NULL; y = &x; *y = 15; foo(y); }
函数foo(int*)
接受一个int
指针作为参数。 因为我已经将y
为int
指针,所以我可以将y
传递给foo
,但是当第一次学习C ++时,我将*
符号与解引用关联起来,因此我认为需要传递一个取消引用的int
。 我会尝试将*y
传递给foo
,这显然不起作用。
拥有一个单独的运算符来声明一个指针会不会更容易? (或取消引用)。 例如:
void test(int@ x) { }
在“C语言的发展”一书中,丹尼斯·里奇这样解释他的推理:
第二个创新最清楚地区分C和它的前辈是这个更完整的types结构,尤其是它在expression语法中的expression…给定一个任何types的对象,应该有可能描述一个新的对象, ,从一个函数产生它,或者是一个指向它的指针…. [这] 导致一个声明语法的名称镜像名称通常出现的expression式语法。 从而,
int i, *pi, **ppi;
声明一个整数,一个指向一个整数的指针,一个指向一个整数指针的指针。 这些声明的语法反映了当在expression式中使用时,i, *pi, and **ppi
都会产生一个int
types。同样,
int f(), *f(), (*f)();
声明一个函数返回一个整数,一个函数返回一个指向一个整数的指针,一个返回一个整数的函数的指针。int *api[10], (*pai)[10];
声明一个指向整数的指针数组,以及一个指向整数数组的指针。在所有这些情况下,variables的声明类似于在声明头部命名的expression式中的用法 。
语法的事故促成了语言的复杂性。 在C语言中拼写*的间接运算符在语法上是一个一元前缀运算符,就像在BCPL和B中一样。在简单expression式中运行良好,但在更复杂的情况下,需要使用括号来指导parsing。 例如,为了区分通过函数返回的值来调用指针指定的函数,分别写入
*fp() and (*pf)()
。 expression式中使用的样式贯穿于声明,所以可能会声明名称
int *fp(); int (*pf)();
在更华丽但仍然现实的情况下,情况变得更糟:
int *(*pfp)();
是指向返回指向整数的指针的函数的指针。有两个效果发生。 最重要的是,C有相对丰富的描述types的方法(与Pascal相比)。 像C-Algol 68这样具有expression能力的语言中的声明 – 描述的对象同样很难理解,因为对象本身是复杂的。 第二个效果是由于语法的细节。 C中的声明必须以“内外”的方式阅读,很多人难以理解。 Sethi [Sethi 81]观察到,如果间接运算符被视为后缀运算符而不是前缀,那么许多嵌套的声明和expression式会变得更简单,但是到那时为时已晚。
如果你这样写,理由就更清楚了:
int x, *y;
也就是说,x和* y都是整数。 因此y是一个int *。
这是一个早于C ++的语言决策,因为C ++从Cinheritance了C语言。我曾经听说动机是声明和使用是等价的,也就是说,给定一个int *p;
的声明int *p;
expression式*p
的int
types与int i;
相同, expression式i
是int
types的。
因为这个委员会和那些在标准化前几十年开发C ++的人决定*
应该保留原来的三个含义 :
- 指针types
- 解除引用操作符
- 乘法
你是正确的build议, *
(和,同样, &
)的多重含义是混淆。 多年来,我一直认为,他们是理解语言新手的重要障碍。
为什么不为C ++select另一个符号?
向后兼容性是根本原因……最好在新的上下文中重用现有符号,而不是通过将先前不是运算符翻译成新的含义来破坏C程序。
为什么不selectC的另一个符号?
当然不可能知道,但是有几个论点可以被制定。 最重要的是这样的想法:
当[an]标识符出现在与声明符相同forms的expression式中时,它将生成指定types的对象。 {K&R,p216}
这也是为什么C程序员倾向于[需要引用]倾向于将他们的星号向右而不是向左alignment,即:
int *ptr1; // roughly C-style int* ptr2; // roughly C++-style
尽pipe这两种语言的程序都是不同的。
专家C程序devise:深C秘密包括以下内容: 然后,有一个C的哲学,对象的声明应该看起来像它的使用。
C编程语言第2版(又名K&R)的第216页包括: 声明符被读为一个断言,当它的标识符出现在与声明符相同forms的expression式中时,它产生一个指定types的对象。
我更喜欢范德林登所说的。
哈哈,我感到你的痛苦,我也有同样的问题。
我认为一个指针应该被声明为&int
因为它是有道理的,指针是一个东西的地址。
过了一段时间,我为自己想,C中的每一个types都必须反向读取
int * const a
是为了我
a constant something, when dereferenced equals an int
。 一些必须被解除引用的东西,必须是一个指针。