【问题标题】:Two different pointer syntax in C which one is right and what's the difference between the two?C中两种不同的指针语法哪一种是正确的,两者之间有什么区别?
【发布时间】:2021-05-24 02:45:14
【问题描述】:

我了解指针的概念,并且我们在函数中使用它们来优化我们使用的空间。
我不明白的是在函数中使用它们时的语法

示例 1:

void fun(int * a)//that means we declared a pointer to an integer type a
{
  *a+=1; 
}
fun(&b);//calling the function for int b=10;

示例 2:

void fun(int * a)//that means we declared a pointer to an integer type a
{
  a+=1;
}
fun(&b);//calling the function for int b=10;

问题:哪一个是正确的,如果他们都是正确的,那么两者之间有什么区别?

在 AKX 回答后编辑: 那么为什么我们在链表中这样做呢?如果我们想改变对象的值而不是指针的地址(在这种情况下是双指针),不应该是**head而不是*head吗??

void push(struct node **head, int data)
{
        struct node* newnode = malloc(sizeof(struct node));
        newnode->data = data;
        newnode->next = *head;
}

push(&head,1);

【问题讨论】:

  • 链表代码是您的第一种情况,只是您访问的值是struct node *,而不是int。 (不过,代码看起来有点可疑:如果只从*head 读取,则不需要指向指针的指针。对于具有给定签名的函数,更常见的是改用*head = newnode(或之前)返回节点。)
  • @m oehm 所以说 node * newnode=* head 和说 node **head 一样??
  • 嗯?不,我是说你的push 函数并没有真正利用你可以从调用函数修改头指针的事实。基本上有两种实现推送值的方法:head = push(head, x)push(&head, x),其中headstruct node *&headstruct head **。您的函数看起来像是介于两者之间的混合体。
  • “哪一个是对的,如果他们都是对的,这两者有什么区别?” - 你试过他们看看有什么不同吗?

标签: c pointers linked-list double-pointer


【解决方案1】:

如果您有int *p,则*p 是指向的值,即int*p += 1 递增 int。另一方面,p 本身就是指针int *p += 1 递增指针,使其指向它所指向的数组的下一个元素。

这应该打印10 20 35:

#include <stdio.h>
void foo(int *p)
{
     p += 1; /* increment the pointer */
    *p += 5; /* add to the pointed-to int */
}

int main(void)
{
    int a[3] = {10, 20, 30};
    foo(&a[1]);     /* address of / pointer to a[1] */
    printf("%d %d %d\n", a[0], a[1], a[2]);
}

这里,

struct node* push(struct node **head, int data)
{
        struct node* newnode = malloc(sizeof(struct node));
        newnode->data = data;
        newnode->next = *head;
        return newnode;
}

head 是指向struct node 的指针,所以*head 是指向struct node 的指针。这就是我们通常要存储在链表中的内容,即指向下一条数据的指针。 **head 将是一个 struct node,即元素本身,从中分配将是制作数据片段的副本。

【讨论】:

    【解决方案2】:

    我了解指针的概念,并且我们在函数中使用它们来优化我们使用的空间。

    这不是我们使用它们的原因(至少这不是主要原因,在现代系统上,int * 可能比int 占用更多空间) - 我们使用它们是因为这是向参数写入新值的唯一方法。

    请记住,C 通过值传递所有函数参数 - 函数中形式参数的任何更改都不会反映在函数调用中的参数中。如果你的函数写成

    void fun( int a )
    {
      a += 1;
    }
    

    并称为

    fun( b );
    

    b 中的值不会受到影响 - a 是一个完全不同的对象,对它的任何更改都不会反映在 b 中。然而,当我们写

    void fun( int *a )
    {
      *a += 1;
    }
    
    fun( &b );
    

    我们不会更新a 的值,我们会更新a 的值指向,在本例中为b

    关于链表示例,它的编写方式不需要headstruct node **,因为它没有得到一个新的指针值写入它;您需要将其称为

    list = push( &list, new_value );
    

    为了正确更新列表指针。

    如果您想更新head 参数,您只需将head 作为struct node ** 传递,如下所示:

    void push( struct node **head, int data )
    {
      struct node *n = malloc( sizeof *n );
      if ( n )
      {
        n->data = data;
        n->next = *head;  // n->next points to the old head of the list
        *head = n;        // n becomes the new head of the list
      }
    }
        
    

    并将其称为

    struct node *list = NULL;  // list is initially empty
    
    push( &list, 42 );
    push( &list, 300 );
    

    等等

    【讨论】:

      【解决方案3】:

      逐字逐句基于 OP 的帖子:

      示例 1 *a=+1; 设置存储在由指向 +1 的指针引用的位置处的值。

      示例 2 a=+1 使指针指向内存地址 1(这可能无效)。

      如果 OP 表示a += 1:

      示例 1 递增存储在指针引用的位置的值(因为 * 是取消引用运算符)。

      示例 2 增加指针本身,使其指向不同的位置,并且增量是指针类型的大小(如果您有数组则方便)。

      【讨论】:

      • @EricPostpischil 我不明白你的评论,你到底是什么意思?
      • @AKX 我的意思是 a+=1 抱歉,我编辑了它。也回复我的其他编辑谢谢
      • ...也许您应该先让OP澄清这个问题...:D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 2018-03-13
      • 2019-05-31
      相关资源
      最近更新 更多