函数中的指针和列表中的指针

时间:2019-02-03 12:35:46

标签: c

当我被介绍到指针时,我被告知它们是有用的,因为它们使我们可以修改输入到通常无法修改的函数中的某些变量。例如:

void copy(int *p, int *s);  

int main(){
  int a = 4, b = 10, *p = &a, *s = &b;
  copy(p, s);
}

void copy(int *p, int *s){
  *s = *p;
  *p = 0;
}

因此,即使“ a”和“ b”通常不可修改,“ b”也等于“ a”,“ a”等于0。

在谈论列表,特别是在列表中添加元素时,我可以使用如下函数:

struct list{
  int n;
  struct list *next;
}

struct list *first = NULL;

int main(){
   int n = 3;
   first = add_to_list(first, n);
}

struct list *add_to_list(struct list *first, int n){
  struct list *new_node;
  new_node = malloc(sizeof(struct list));
  if(new_node == NULL) exit(EXIT_FAILURE);
  new_node->value = n;
  new_node->next = first;
  return new_node;
}

我特别关心的是为什么函数不能简单地返回void类型,而不是编写“ return new_node” ,而不是简单地编写“ first = new_node” 。因为first是指针,所以如果我在程序中的任何地方修改它,原始指针也应该修改,就像我在第一个示例中发生的那样,对吗?

另外,还有一个无关的问题,但是如果我有这样的功能:

void first_to_n(int a[], int n){
  a[0] = n;
}

可以说是在main中声明的原始向量a的第一个元素也被修改了,对吗?因为向量可以视为指针

4 个答案:

答案 0 :(得分:1)

  

当我被介绍给指针时,我被告知它们是有用的,因为它们使我们可以修改输入到通常无法修改的函数中的某些变量。

除其他事项外,例如创建非平凡的数据结构并避免复制。

  

因为第一个是指针,所以如果我在程序中的任何地方修改它,那么原始指针也应该修改,就像我在第一个示例中发生的那样,对吗?

first(参数)是first(全局)的副本。因此,first = new_node仅会修改您的指针,而不会修改全局指针。

这在您的第一个示例中更加清楚:

void copy(int *p, int *s){
  *s = *p;
  *p = 0;
}

例如,如果您正在做p = 0;,则只修改指针,而不修改指向的值。

  

可以说是在main中声明的原始向量a的第一个元素也被修改了,对吗?因为向量可以视为指针

那不是一个“向量”(数组),即使它看起来像一个数组,它也是一个指针。这是C的一大难题。

但是,实际上,a[0] = 0;正在修改参数所指向的第一个值(在main中)。

答案 1 :(得分:1)

让我们说我们有类似下面的代码

void funcA(int x)
{
    x = 0;
}

void funcB(int *y)
{
    y = NULL;
}

int main(void)
{
    int a = 10;
    int *b = &a;

    funcA(a);
    funcB(b);
}

调用funcA时发生的事情是将a value 复制到函数内部的单独变量x中。进行呼叫时,值10的两个副本存储在不同的位置。当在函数内部完成分配x = 0时,仅修改局部变量x

对于funcB也会发生同样的情况。变量b value 被复制到函数中单独的变量y中。这意味着有两个单独且不同的变量指向同一位置。但是一旦分配y = NULL完成,那就不再是事实。变量y不再指向相同的位置,但是在main函数中b未被修改,因为仅将值的副本传递给了该函数。


如果我们现在举一个稍微不同的例子

void func(int *x, int **y)
{
    *y = x;
}

int main(void)
{
    int a = 10;
    int b = 20;
    int *c = &a;  // Make c point to the variable a

    func(&b, &c);
}

调用函数后,c不再指向a,而是指向b。这是因为对于第二个参数,我们传递的值为&c,它是指向变量c的指针。然后,在函数内部,我们可以使用解引用运算符访问y指向的内容(在c函数中将成为变量main)。

答案 2 :(得分:0)

  

我特别关心的是为什么函数不能简单地返回   类型无效,除了写“ return new_node”,我不能简单地   写“ first = new_node”。

正如其他答案所解释的,您不能因为first是函数外部指针的“副本”。但是,如果要改为更改函数,以使您将“指针指向指针”传递给了指针,而不是仅传递了“指针”,则可以更改外部值,即“复制”函数中的内容。 / p>

答案 3 :(得分:0)

这使用指向文字字符串的指针。
指针将传递到modifypointer(),在此处它被修改为指向另一个文字字符串。新的文字字符串将打印在函数中,但是main()仍会打印原始字符串。
指针在modifypointertopointer()中作为指向自身的指针传递,在该指针中,该指针被取消引用以指向另一个文字字符串。现在,该函数将打印新的文字字符串,而main()也将打印新的文字字符串。
在您的最后一个示例中,可以使用first = new_node;,但该函数声明了影子变量first并且全局first不在函数范围内。

#include <stdio.h>

void modifypointer( char *mod) {
    mod = "modify pointer";
    printf ( "%s\n", mod);
}

void modifypointertopointer( char **ptrmod) {
    *ptrmod = "modify pointer to pointer";
    printf ( "%s\n", *ptrmod);
}

int main( void) {
    char *text = "original";
    printf ( "%s\n", text);
    modifypointer ( text);
    printf ( "%s\n", text);
    modifypointertopointer ( &text);
    printf ( "%s\n", text);
    return 0;
}