c++ 为什么解引用操作符(*)也用于声明指针?

dffbzjpn  于 2023-05-08  发布在  其他
关注(0)|答案(6)|浏览(145)

我不确定这是否是一个适当的编程问题,但它一直困扰着我,我想知道我是否是唯一一个。
在最初学习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)
{
}
xytpbqjk

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]观察到,如果间接操作符被用作后缀操作符而不是前缀,许多嵌套的声明和表达式会变得更简单,但到那时改变已经太晚了。

31moq8wy

31moq8wy2#

如果你这样写的话,原因就更清楚了:

int x, *y;

也就是说,x和 *y都是整数。因此,y是int *。

m1m5dgzv

m1m5dgzv3#

这是一个早于C的语言决定,因为C继承了C。我曾经听说过这样做的动机是声明和使用是等价的,也就是说,给定一个声明int *p;,表达式*p的类型是int,就像int i;的表达式i的类型是int一样。

bq3bfh9z

bq3bfh9z4#

因为委员会,以及在C标准化之前几十年里开发C的人,决定***应该保留它原来的三个含义**:

  • 指针类型
  • 解引用运算符
  • 乘法

您认为*(以及类似的&)的多重含义令人困惑是正确的。多年来,我一直认为它们是语言新手理解的一个重大障碍。

为什么不为C++选择另一个符号?

向后兼容是根本原因……最好在新的上下文中重用现有的符号,而不是通过将以前的非运算符转换为新的含义来破坏C程序。

为什么不为C选择另一个符号?

这是不可能知道的肯定,但有几个论点,可以-并已-作出。最重要的是这样一个想法:
当[an]标识符出现在与声明符相同形式的表达式中时,它产生指定类型的对象。{K&R,p216}
这也是为什么C程序员倾向于将星号向右对齐而不是向左对齐的原因,即:

int *ptr1; // roughly C-style
int* ptr2; // roughly C++-style

尽管在两种语言的程序中都不同地发现了这两种变体。

l5tcr1uw

l5tcr1uw5#

Expert C Programming: Deep C Secrets的第65页包括以下内容:* 然后,还有C哲学,即对象的声明应该看起来像它的使用。
The C Programming Language, 2nd edition (aka K&R)的第216页包括:* 声明符被读取为Assert,当其标识符出现在与声明符相同形式的表达式中时,它会产生指定类型的对象。
我更喜欢货车林登登的说法。

lnlaulya

lnlaulya6#

哈哈,我能感受到你的痛苦,我也有同样的问题。
我认为指针应该声明为&int,因为指针是某个东西的地址。
过了一段时间,我自己想,C中的每一种类型都可以向后读,就像
int * const x
可以读作
x const * int
常量x在解引用时(用*表示)是int类型。所以必须要被解引用的东西,必须是指针。

相关问题