通常,我知道一个指针存储位于计算机内存中的另一个值的内存地址,例如:
int firstvalue= 5
int * p1;
p1 = &firstvalue; // p1 = address of firstvalue
如果我们在链接列表中定义如下操作,会发生什么? *current=*list
是否意味着current指向的值等于list指向的值?如果我们定义ecur=current
是什么意思?
int function(struct list_t **list){
struct list_t *ecur=NULL;
struct list_t *current=*list;
ecur=current;
}
更新:
*list=remove(*list, param1, param2)
有什么作用?那为什么呢?
remove
是一个返回list
修改列表的函数。
更新2:
为什么我们需要定义一个指向指针的指针才能修改列表? *list
是指向指针的指针吗?
答案 0 :(得分:2)
变量list
是指向结构list_t的指针。如果我们(仅作为示例)假设该结构放置在地址2000处,而未命名的指针位于地址1000处,它将看起来像这样:
然后,您将进行初始化,并添加了两个新变量。两者都是指向结构体list_t的指针。
struct list_t *ecur=NULL;
struct list_t *current=*list;
现在图片变成:
请注意,current
与中间的“ some-pointer”具有相同的值,因为分配给*list
的是current
。
然后您有任务:
ecur=current;
这意味着ecur
获得与current
相同的值并给出图片:
更新:
*list=remove(*list, param1, param2)
会做什么?
它更改图片中间的“指针”的值。例如,如果remove
函数删除了链表中的第一个元素,则需要这样做。
答案 1 :(得分:1)
为什么我们需要定义一个指针以修改列表? * list是指向指针的指针吗?
请记住,C会按值传递所有函数参数-函数定义中的形式参数是内存中与函数调用中实际参数不同的对象。例如:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a
是与x
不同的内存对象,并且b
是与y
不同的内存对象,因此交换a
和{{ 1}}对b
和x
无效。为了交换y
和x
的值,必须将 pointers 传递给它们:
y
表达式 void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
与*a
相同,因此写入x
与写入*a
相同。 x
和*b
相同。
因此,要使函数写入参数,必须将 pointer 传递给该参数:
y
对于任何非数组类型void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
,这都是正确的。让我们用指针类型T
替换T
:
P *
语义完全相同-所更改的只是类型。
如果某个函数有可能修改void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
对象(例如,将其指向新的列表头),则必须将指针传递给该list *
对象:
list *
答案 2 :(得分:0)
TYPE *p = ptype /*variable of type: TYPE * */;
不是分配。这是一个初始化,对于auto
-matic(=堆栈上)p,可以重写为:
TYPE *p;
p = ptype;
(不是TYPE *p; *p=ptype; /*would be a type error*/
)
就您的示例而言:
struct list_t *current=*list;
设置current
指向的位置(与*list
指向的位置相同(*list
也是一个指针,因为list
是一个双向间接指针))初始化后无需对指向(*current
的电流进行任何操作。
所有这些只是概念上的。您的函数没有任何外部可见的效果,因此优化的编译器应完全删除其主体。
答案 3 :(得分:0)
我和this post的想法相似。我想对您的功能进行一些重新安排,以便更轻松地了解发生了什么:
int function(struct list_t **list)
{
struct list_t *current = *list;
struct list_t *ecur = current;
}
如果我们使用元素foo
调用此函数,则基本上可以得到以下信息:
struct list_t foo = { .data = "foo" };
struct list_t *bar = &foo;
struct list_t **list = &bar;
struct list_t *current = *list;
struct list_t *ecur = current;
我们有五个声明和五个作业。为了提高可读性,我将所有内容都记下来而不声明:
foo = { .data = "foo" };
bar = &foo;
list = &bar;
current = *list;
ecur = current;
现在,让我们来看一下:
foo
是一个结构。它包含上面的数据字段。bar
是指向struct的指针。它包含foo
list
是指向struct的指针。它包含bar
current
是指向struct的指针。它包含list
内容的内容,它是foo
的地址ecur
是指向struct的指针。它与current
相同,并且包含地址bar
最后,我们可以将整个示例简化为:
struct list_t foo = { .data = "foo" };
struct list_t *ecur = &foo;
这是什么意思?
list
:由于list
是指向指针的指针,因此您可以通过取消引用bar
来修改*list = ...
使其指向完全不同的内容(current
) ecur
/ bar
:这也是(*ecur).data = "banana"
最初的指向。通过取消引用,您可以更改数据字段本身(ecur->data
或更好的class StreamCount:
def __init__(self, input_values):
self.input_values = input_values
self.output = []
self.current_value = next(iter(input_values), None) # first element if there is any
self.current_count = 0
def process_new(self, value):
if value == self.current_value:
self.current_count += 1
else:
self.update_output()
self.current_count = 1
self.current_value = value
def process_all(self):
for v in self.input_values:
self.process_new(v)
# handle last values suite
self.update_output()
return self.output
def update_output(self):
if self.current_count > 2:
self.output.append(self.current_value)
else:
self.output += [self.current_value for _ in range(self.current_count)]
)我希望我能澄清一些事情,并且不要让它变得更糟;)
答案 4 :(得分:0)
为什么我们需要定义一个指向该指针的指针才能修改 清单?
让我添加一个完整的程序,尽管简短,以更好地说明它。它定义一个简单的链表并在保持顺序的同时进行构建。是的,我知道简单地调用qsort()
会更容易,但是我想展示一下如何添加一个间接级别(指向指针的指针)可以平滑地插入元素,而无需测试特殊情况。
// C pointer exercise: sort arguments
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
struct list
{
char *arg;
struct list *next;
};
int main(int argc, char *argv[])
{
// pointer to base, running pointer and pointer to pointer
struct list *base = NULL, *p, **pp;
for (int i = 1; i < argc; ++i)
{
struct list *new_entry = malloc(sizeof(struct list));
if (new_entry)
{
new_entry->arg = argv[i];
// find where to insert new entry
for (pp = &base; *pp; pp = &(*pp)->next)
if (strcasecmp(new_entry->arg, (*pp)->arg) < 0)
break;
// insertion in a simply linked list
new_entry->next = *pp;
*pp = new_entry;
}
}
// display and cleanup
for (p = base; p;)
{
struct list * tmp = p->next;
puts(p->arg);
free(p);
p = tmp;
}
return 0;
}