知道在C中的方法定义中使用的星号数量?

时间:2010-10-18 14:47:39

标签: c pointers

例如:

void DeleteLastNode(NodeType **L)

如果** L代表变量L的地址,那么它是否可以不用& L代替?另外,如果我使用* L或只是L,我是否能够改变L'的内容?如果是这样,使用* L和L的区别是什么,如果L是指向它的指针呢?我是否只能通过发送L并在实际方法中使用* L来查看它的内容?

我想我的指针仍然不太好。

6 个答案:

答案 0 :(得分:5)

据我所知,一个星号表示C中的普通指针。例如,您可以分配内存并使指针指向新分配的区域。您还可以指向堆栈中的变量,如:

int x = 10;
int *p = &x;

但是在某些情况下,您希望将指针传递给函数,并使该函数能够将指针更改为指向另一个地址。现在我们不是在谈论通过指针改变变量的内容,也不是通过它指向的内存来改变变量的内容,但是文学会改变指针信息(这是一个mem。地址)来指向另一个地方。在这种情况下,我们使用指向由双星号表示的指针的指针。

int x, y;
int *p;
int **pp;

pp = &p;  //pp points to pointer p
*pp = &x; //pp changes pointer p to point to variable x
*p = 10;  //p (now points to x) assigns value 10 to x
*pp = &y; //pp changes pointer p again assigning the address of y
*p = 20;  //p assigns 20 to y;
**pp = 25;// that's tricky, the first * give access to the address pointed by p (&y) the second changes the content of that address to 25. so now y ends with 25

最后x = 10且y = 25

现在特别针对您的情况,该函数调用看起来像一个将从链表中删除节点的函数。这是有道理的,因为你有一个指向列表头部的外部指针。删除最后一个元素时,函数必须能够将指针从当前地址更改为null。您可以使用全局指针或在您的情况下传递头指针的地址。

答案 1 :(得分:1)

让我们清楚一些事情。从技术上讲,L是指向NodeType实例的指针。但是,函数的名称提供了不同的解释:可能L是指向数组的指针的地址或NodeType实例的链接列表(您必须参考函数的文档来验证这一点)。

如果是这种情况,那么函数通常会像这样使用:

NodeType *list = malloc (5 * sizeof(NodeType));
/* do something with the list, e.g. put entries into it */
DeleteLastNode (&list);  /* delete last node in list */

该函数可能会修改指向数组/列表的变量,这就是为什么你必须将 list 的地址传递给函数。

但是要说具体的话,我们需要有关DeleteLastNode()的更多信息。

答案 2 :(得分:0)

不,不在C中,函数体中的星号不能替换为函数体中的&符号(&)。在C ++中,它是另一回事。人们认为有些类似的想法,并在决定C ++的功能时添加了这个功能。

答案 3 :(得分:0)

可能有助于理解的东西

NodeType **L

表示L是指向NodeType对象的指针。

例如,如果是

NodeType *P

然后P是指向NodeType对象的指针,如果P是0xE0101010,并且每个NodeType对象是80字节,则P + 1将是0xE0101060(0xE0101010加0x50 = 0xE0101060)。

然后让我们看看L,它指向NodeType的指针。如果我们认为指针是4个字节,那么如果L是0xE0202020,而L + 1将只是0xE0202024。

因此,只要涉及指针算术,使用正确的类型就很重要。注意L [3]与*(L + 3)相同,因此L [3]涉及指针算术,因此指针类型需要非常精确,否则当你查看指针所指向的内容时通过* L,即调用解除引用,然后可能发生分段错误(Unix / Linux)或GP错误(Windows)。

答案 4 :(得分:0)

NodeType nt;
NodeType *pnt = &nt;

--------         ------
| pnt  |-------->| nt |
--------         ------

此处pntpnt的内容)为&nt; *pntnt

NodeType **L = &pnt;

------        --------         ------
| L  |------->| pnt  |-------->| nt |
------        --------         ------

现在LL的内容)为&pnt; *Lpnt;因此**L*pnt,即nt。请注意,*& 相互取消*L -> *&pnt -> pnt)。

答案 5 :(得分:0)

如果** L代表变量L的地址,那么它不能被& L代替吗?

**L表示L指向的位置所指向的位置处的。为了说明,假设以下声明:

int     a =   1;
int  * pa = & a; // whitespace doesn't matter here
int **ppa = &pa;

ppa指向paa又指向1,其值为*。这是一个假设的记忆图,显示了它们之间的关系(假设是32位整数,大端):

Object       Address        0x00  0x01  0x02  0x03
------       -------        ----------------------
     a       0x10008000     0x00  0x00  0x00  0x01
    pa       0x10008004     0x10  0x00  0x80  0x00 
   ppa       0x10008008     0x10  0x00  0x80  0x04

声明符中,*运算符表示此变量是指针并保存另一个变量的地址。在表达式中,&运算符生成指针指向的值。在 C ++ 声明符中,&运算符表示此变量是引用并且是同义词对于另一个变量(它不一定与指针相同; C不允许声明符中的&)。在表达式中,{{1}}运算符生成其操作数的地址

因此,按照上面的内存映射,以下所有内容都是正确的:

    a == 1;
 * pa == 1; // again, whitespace doesn't matter here.
**ppa == 1; 

   &a == 0x10008000;
   pa == 0x10008000;
 *ppa == 0x10008000;

  &pa == 0x10008004;
  ppa == 0x10008004;

 &ppa == 0x10008008;