探讨c/c++的指针

最近写项目时遇到个指针坑,决定记录一下。

看下面代码,猜下运行结果

#include <bits/stdc++.h>

using namespace std;

int number1 = 1;
int number2 = 2;
void f(int *a) {
    a = &number2;
}
int main() {
    int *p = &number1;
    f(p);
    printf("%d\n", *p);
    return 0;
}

运行结果是1。

之前用指针有一个误区,指针只是指向某个类型的地址,指针本身也是一个类型,所以当参数传入时,已经不是同一个指针了。可以尝试输出a和p的地址,会发现是不一样的。

(PS:这坑在java上更明显,因为java对象引用实质和指针一样,所以改变参数的指向不是一个好方法)

对于上面的代码,可以做如下改进:

方案一:进行内存赋值操作

#include <bits/stdc++.h>

using namespace std;

int number1 = 1;
int number2 = 2;
void f(int *a) {
    *a = number2;
}
int main() {
    int *p = &number1;
    f(p);
    printf("%d\n", *p);
    return 0;
}

方案二:传入指针的地址进行操作

#include <bits/stdc++.h>

using namespace std;

int number1 = 1;
int number2 = 2;
void f(int **a) {
    *a = &number2;
}
int main() {
    int *p = &number1;
    f(&p);
    printf("%d\n", *p);
    return 0;
}

这里顺便探讨下指针可以有多少级,其实理论上指针可以无限级。这样可能有个疑惑,那我指针的指针的指针……编译器是如何定义的呢,定义一个指针时如果有那么多地址他又是如何分配内存?我们尝试输出一下。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int number = 0;
    printf("%p %p\n", &number, &(&number));
    return 0;
}

发现编译错误,提示error: lvalue required as unary '&' operand。我们换一种写法。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int number = 0;
    int *p = &number;
    printf("%p %p\n", p, &(p));
    return 0;
}

好,这样是可以成功编译的。我们再试一下,再开一个指针。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int number = 0;
    int *p = &number;
    int **pp = &p;
    //编译错误
    //printf("%p %p %p\n", p, &(p), &(&p));
    
    //编译成功
    printf("%p %p %p\n", p, &(p), &(pp));
    return 0;
}

好,得出结论。编译器本身不会管你有多少级指针,这都是你自己分配的,至于能分配多少个取决于内存大小。编译器只负责定义类型,在某个地址的内存存下你的数据。至于指针,则是另一种数据类型,而他存的值就是他所指向的地址。

 

posted @ 2018-08-10 12:02  酱油党gsh  阅读(112)  评论(0编辑  收藏  举报