简体   繁体   English

C 指向指针并通过引用传递

[英]C Pointer to Pointer and Pass by Reference

I'm trying to learn C, and I'm hung up a bit on Pointers to Pointers.我正在尝试学习 C,我对指针的指针有点挂断。 I think I understand why you need them, but can't quite get my head wrapped around what is happening.我想我理解你为什么需要它们,但不能完全理解正在发生的事情。

For instance, the following code doesn't seem to work as I would expect it to:例如,下面的代码似乎不像我期望的那样工作:

#include <stdio.h>

int newp(char **p) {
  char d = 'b';
  *p = &d;
  /*printf("**p = %c\n", **p);*/
  return 1;
}

int main() {
  char c = 'a';
  char *p = &c;
  int result;

  result = newp(&p);
  printf("result = %d\n", result);
  printf("*p = %c\n", *p);
  printf("c = %c\n", c);

  return 0;
}

The result I get is this:我得到的结果是这样的:

result = 1
*p = 
c = a

*p prints as nothing. *p 打印为空。 Instead, I would expect *p = b .相反,我希望*p = b

However , if I uncomment line 6 (the printf in the newp function), then I get this:但是,如果我取消注释第 6 行( newp函数中的printf ),那么我会得到:

**p = b
result = 1
*p = b
c = a

What am I missing?我错过了什么?

You are dealing with undefined behaviour.您正在处理未定义的行为。 The variable d is local (resides on the stack) and is not available after the enclosing function ( newp ) returns.变量d是本地的(驻留在堆栈上)并且在封闭的 function ( newp ) 返回后不可用。

When dereferencing p outside newp , the address on the stack &d may be overwritten by some other local variable or it may contain garbage.当在newp之外取消引用p时,堆栈&d上的地址可能会被其他一些局部变量覆盖,或者它可能包含垃圾。

You are storing the address of a local variable ( d ) in *p and then dereferencing it when the variable has gone out of scope.您将局部变量 ( d ) 的地址存储在*p中,然后在变量超出 scope 时取消引用它。 Undefined Behavior未定义的行为

You might be "missing" the keyword static , as in:您可能“缺少”关键字static ,如:

int newp(char **p) {
    static char d = 'b';   /* <--- HERE */
    *p = &d;
    /*printf("**p = %c\n", **p);*/
    return 1;
}

This static keyword causes the compiler to locate the local variable in "static storage," which continues to exist (ie maintains its value) during the time periods after newp() has been called.这个static关键字使编译器将局部变量定位在“静态存储”中,该局部变量在调用newp()之后的时间段内继续存在(即保持其值)。 However, there is only one copy of this memory -- each subsequent invocation of the containing function ( newp ) re-uses the same memory location and may overwrite the value at that time.但是,此 memory 只有一个副本 - 包含 function ( newp ) 的每个后续调用都重新使用相同的 memory 位置并可能覆盖当时的值。

Without the static keyword to qualify your local variable declaration, the storage will be "automatic", which means that it is automatically discharged from current use after the containing function has returned.如果没有static关键字来限定您的局部变量声明,则存储将是“自动”的,这意味着在包含 function 已返回后,它将自动从当前使用中解除。 After newp returns, the memory formerly used for the local variable can be reused for any purpose. newp返回后,以前用于局部变量的 memory 可以用于任何目的。

#include <stdio.h>

// Here *pointer means that the parameter that this function 
// will expect will be a pointer. 
void changeViaPointer(int *pointer);

// Pointer of a pointer.
void changeViaPointerInBetween(int **pointer);

int main(){

    int number;
    number = 20;

    // Here *pointer means that the variable that is declared will be a pointer.
    int *pointer;

    // Actually asigning value to the pointer variable.
    pointer = &number;

    // Pointer of a pointer.
    int **pointerInBetween;

    // Assigning value to the pointer of a pointer. 
    // Assigning the memory location where this pointer points to. 
    // So this is a pointer in between.
    pointerInBetween = &pointer;

    printf("The number before changing is %d\n", number);

    // Pass the pointer variable.
    changeViaPointer(pointer);
    printf("The number after pointer changing is %d\n", number);

    // Pass the pointer of a pointer variable.
    changeViaPointerInBetween(pointerInBetween);
    printf("The number after pointer in between changing is %d\n", number);

    return 0;
}

void changeViaPointer(int *pointer){

    // Okay, at this point we have received a variable called pointer,
    // which points to some value. In order to access this value
    // we need to use *pointer.
    // BUT THIS IS DIFFERENT FROM THE *pointer IN THE FUNCTION DECLARATION!!!
    *pointer = *pointer + 20;
}

void changeViaPointerInBetween(int **pointer){

    // **pointer explanation:
    // Only pointer is the memory location
    // *pointer  is the value of that memory location, which in this specific case is also a memory location
    // **pointer is the value of what the other pointer points to.
    **pointer = **pointer + 20;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM