C指针和指针传递指针

时间:2011-06-28 16:50:49

标签: c pointers

我正在努力学习C语言,而且我在指针指针上挂了一点。我想我明白你为什么需要它们,但不能完全理解正在发生的事情。

例如,以下代码似乎不像我期望的那样工作:

#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;
}

我得到的结果是:

result = 1
*p = 
c = a

* p打印为空。相反,我希望*p = b

但是,如果我取消注释第6行(printf函数中的newp),那么我会得到这个:

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

我错过了什么?

4 个答案:

答案 0 :(得分:8)

您正在处理未定义的行为。变量d是本地的(驻留在堆栈上),并且在封闭函数(newp)返回后不可用。

p之外取消引用newp时,堆栈&d上的地址可能会被其他一些局部变量覆盖,或者它可能包含垃圾。

答案 1 :(得分:6)

您正在d中存储局部变量(*p)的地址,然后在变量超出范围时取消引用它。 Undefined Behavior

答案 2 :(得分:1)

您可能“缺少”关键字static,如:

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

static关键字使编译器在“静态存储”中定位本地变量,该静态存储在调用newp()后的时间段内继续存在(即保持其值)。但是,此内存只有一个副本 - 每次后续调用包含的函数(newp)都会重新使用相同的内存位置,并可能会覆盖此时的值。 / p>

如果没有static关键字来限定本地变量声明,则存储将是“自动”的,这意味着在包含函数返回后它将自动从当前使用中释放。在newp返回后,以前用于局部变量的内存可以用于任何目的。

答案 3 :(得分:0)

#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;
}