【问题标题】:Why these two code snippets equivalent to each other (Pointers)为什么这两个代码片段彼此等价(指针)
【发布时间】:2013-09-13 15:54:14
【问题描述】:

我正在编写一个函数来查找链表的长度。我的问题特定于指针的声明。

int lengthOfLinkedList(Node *head) 
{ 
Node* current = head; 
}

vs. 

int lengthOfLinkedList(Node *head) 
{
Node* current = NULL; 
current = head; 
}

所以这是我的理解: 在第一个示例中,声明了一个指向 Node 对象的指针,它取消了对头指针地址的引用。


|内存地址 |


这不是我想做的。相反,我想尊重指针,以便我可以访问它指向的节点(这是我在第二个代码 sn-p 中所做的):


|数据| *下一个|


所以现在我认为指针在初始化它们时的行为会有所不同——你可以在使用 ('*') 运算符初始化它时直接声明指向内存地址的指针,但在初始化后你不能再这样做了。这很奇怪..

我是对的还是发生了其他事情?

【问题讨论】:

  • 第一个用head中的值初始化current。第二个使用值NULL 初始化current,然后将head 中的值分配给current
  • current 是“指向节点的指针”类型。两个代码 sn-ps 都做同样的事情。声明中第一个初始化的“current”。第二个首先将“current”初始化为 NULL,然后在赋值语句中将其重置为“head”。
  • 请记住,指针仍然由一个值(内存地址)表示,current 的值在任何一种情况下都将等于head 的值。

标签: c++ c pointers


【解决方案1】:

这两个sn-ps是完全等价的;在这两种情况下,* 都是 not 解引用运算符(就像它出现在表达式中一样),但它只是用于声明指针的标记。换句话说,这里*逻辑上1Node一起(指定Node*的类型,即“指向Node的指针”2),不是current

(对于两个完全不同的事物(声明中的指针说明符,表达式中的一元运算符3)这种令人困惑的重复使用相同字符的事实来自于这样一个事实,即“声明应该模仿用法” ",因此,由于要访问使用* 的指针的值,它甚至用于声明它们。)

在第一种情况下,current 从头开始​​具有相同的head 值,在第二种情况下首先初始化为NULL,然后更改为具有相同的head 值;在这两种情况下,函数结束时的结果完全相同。


  1. 遗憾的是,它在语法上与current 一起使用,因为在声明中,“指针类型说明符”绑定到特定变量;即,如果你写int * ptr1, ptr2;ptr1 将是int * 类型,而ptr2 将是一个普通的int

  2. 指针声明最好从右向左阅读(const char *:指向字符常量的指针;char * const:指向字符的常量指针;等等);更一般的声明(例如函数指针)是way messier

  3. 还有二元乘法运算符,但通常不会混淆(它适用于不同的类型,并且放在两个操作数之间)。

【讨论】:

  • 有趣。所以 * 用于声明一个指针,然后 [i]after[/i] 它已被初始化,您可以使用 * 取消引用它。难怪为什么指针对很多人来说如此混乱。一个操作员执行两个不同的功能
  • @user2202911:我同意,一开始这很令人困惑,几乎我认识的每个学习过 C 或 C++ 的人都被这种模棱两可所困扰(顺便说一下,请注意在声明中它不是运算符,它只是一个标记,用于指定我们要声明一个指针)
  • @user2202911 很多 C 书籍在类型和星号之间放置了空格,只是为了让初学者彻底混淆。
  • @Theodoros:他们这样做是因为注释1中解释的原因。至于我,我前后都放了空格,以激怒最多的人。
  • 注释1的答案:每条语句不要声明多个变量。这个特性是 C 的保留,从那时所有变量必须在函数顶部声明,并且在编写良好的 C++ 中没有位置。 (如果你在 C 中有一个嵌套循环,那么声明索引 int i, j; 是有意义的。在 C++ 和现代 C 中,你可以将声明直接放在 for 中。)
【解决方案2】:

在这两个示例中都没有取消引用。两者都只是将传递的指针分配给一个新变量,然后在函数退出时将其丢弃。

考虑这个顺序

int x = 0;
x = 2;

对比

int x = 2;

【讨论】:

    【解决方案3】:

    初始化赋值不同;您没有在初始化中取消引用current* 只是用来表示current 有一个指针类型,仅此而已。

    C 和 C++ 声明语法基于 表达式 的类型,而不是对象。例如,如果您有一个指向整数的指针,并且想要获取该整数值,则必须使用一元 * 运算符取消引用该指针:

    x = *p;
    

    表达式*p的类型是int,所以p的声明是

    int *p;
    

    在声明中,* 标记只是用来提供额外的类型信息;也就是说,p 是指向int 的指针。需要注意的是,对于指针声明 T *p* 绑定到声明符,而不是类型说明符。 IOW,T *p; 被解析为T (*p);。因此,如果要在单个声明中声明多个指针,则必须编写

    T *p, *q, *r;
    

    在这种情况下,pqr 中的每一个都是指向 T 类型的指针。

    很多 C++ 程序员使用T* p; 风格,因为他们觉得强调对象的类型p 更重要,而且有时它会使代码的意图更清晰。但是,它将始终被解析为T (*p);

    【讨论】:

      【解决方案4】:

      为了帮助将指针声明与取消引用分开,请考虑在取消引用时使用箭头运算符->。例如*current.data等价于current->datacurrent->next 会给你当前的下一个指针指向的节点。

      【讨论】:

      • 这没有回答问题,也是错误的。 *current.data等同于current->data,而(*current).data 是。
      • 很公平。我没有足够的声誉来发表评论,所以我同意我选择了不好的答案来发表评论。作者说“我想尊重指针,这样我就可以访问它指向的节点”,并且我提出了这样做的替代选项 - 注意到他的帖子已经得到答复。
      猜你喜欢
      • 1970-01-01
      • 2021-01-06
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 2014-07-28
      • 2019-08-14
      相关资源
      最近更新 更多