我不确定这是否是一个适当的编程问题,但它一直困扰着我,我想知道我是否是唯一一个。
在最初学习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)
{
}
6条答案
按热度按时间xytpbqjk1#
在The Development of the C Language中,Dennis里奇这样解释他的推理:
第二个最清楚地将C与它的前辈区分开来的创新是这种更完整的类型结构,特别是它在声明语法中的表达。给定一个任何类型的对象,应该可以描述一个新的对象,它将多个对象聚集到一个数组中,从函数中产生它,或者是指向它的指针。[这] * 导致了名称的声明语法,该声明语法与名称通常出现的表达式语法的声明语法镜像。
int i, *pi, **ppi;
声明一个整数,一个指向整数的指针,一个指向整数的指针。这些声明的语法反映了这样一个观察结果,即i, *pi, and **ppi
在表达式中使用时都会产生int
类型。类似地,
int f(), *f(), (*f)();
声明一个返回整数的函数,一个返回整数指针的函数,一个返回整数的函数指针。int *api[10], (*pai)[10];
声明一个指向整数的指针数组和一个指向整数数组的指针。句法的偶然性使人们感觉到这种语言的复杂性。在C中拼写为 * 的间接操作符在语法上是一个一元前缀操作符,就像在BCPL和B中一样。这在简单的表达式中很有效,但在更复杂的情况下,需要使用括号来指导解析。例如,为了通过函数返回的值与调用指针指定的函数来区分间接性,可以分别写
*fp() and (*pf)()
。表达式中使用的样式会传递到声明中,因此可以声明名称int *fp(); int (*pf)();
在更华丽但仍然现实的情况下,情况变得更糟:
int *(*pfp)();
是一个指针,指向一个返回整数指针的函数。有两种效果发生。最重要的是,C语言有一套相对丰富的描述类型的方法(与Pascal相比)。例如,像C-Algol 68这样有表达力的语言中的声明描述的对象同样难以理解,这仅仅是因为对象本身很复杂。第二个效果是由于语法的细节。C中的声明必须以一种“由内而外”的风格阅读,许多人发现这很难理解。Sethi [Sethi 81]观察到,如果间接操作符被用作后缀操作符而不是前缀,许多嵌套的声明和表达式会变得更简单,但到那时改变已经太晚了。
31moq8wy2#
如果你这样写的话,原因就更清楚了:
也就是说,x和 *y都是整数。因此,y是int *。
m1m5dgzv3#
这是一个早于C的语言决定,因为C继承了C。我曾经听说过这样做的动机是声明和使用是等价的,也就是说,给定一个声明
int *p;
,表达式*p
的类型是int
,就像int i;
的表达式i
的类型是int
一样。bq3bfh9z4#
因为委员会,以及在C标准化之前几十年里开发C的人,决定**
*
应该保留它原来的三个含义**:您认为
*
(以及类似的&
)的多重含义令人困惑是正确的。多年来,我一直认为它们是语言新手理解的一个重大障碍。为什么不为C++选择另一个符号?
向后兼容是根本原因……最好在新的上下文中重用现有的符号,而不是通过将以前的非运算符转换为新的含义来破坏C程序。
为什么不为C选择另一个符号?
这是不可能知道的肯定,但有几个论点,可以-并已-作出。最重要的是这样一个想法:
当[an]标识符出现在与声明符相同形式的表达式中时,它产生指定类型的对象。{K&R,p216}
这也是为什么C程序员倾向于将星号向右对齐而不是向左对齐的原因,即:
尽管在两种语言的程序中都不同地发现了这两种变体。
l5tcr1uw5#
Expert C Programming: Deep C Secrets的第65页包括以下内容:* 然后,还有C哲学,即对象的声明应该看起来像它的使用。
The C Programming Language, 2nd edition (aka K&R)的第216页包括:* 声明符被读取为Assert,当其标识符出现在与声明符相同形式的表达式中时,它会产生指定类型的对象。
我更喜欢货车林登登的说法。
lnlaulya6#
哈哈,我能感受到你的痛苦,我也有同样的问题。
我认为指针应该声明为
&int
,因为指针是某个东西的地址。过了一段时间,我自己想,C中的每一种类型都可以向后读,就像
int * const x
可以读作
x const * int
常量
x
在解引用时(用*
表示)是int
类型。所以必须要被解引用的东西,必须是指针。