C语言中的指针使用

在C语言中,操作内存是通过指针来实现的。指针可以看做是一种特殊的数据结构,它不但记录了目标对象的首字节地址,还保存了对象的类型。由于,我们知道一个对象的首字节地址和对象类型(对象大小),也就确定了对象的值。

指针通常是这样表示的int *p,*左侧是指针的类型:

int val = 123;
int* p = &val;
printf("%d %d\n",p,*p); 

在上面的示例中,&val用来对目标对象取地址操作,并赋值给指针p. %d用来输出一个整数值,地址本身就是一个整数值,*p解引用得到该目标对象的值。

作为参数传递

在C语言里,参数传递是挺让人困扰的地方。因为涉及到了指针,参数可能说变就变。:–(

尽管如此,有一些规则还是有迹可循的。首先,参数是以copy的形式传递到函数内部的。也就是说,传入函数内部的是一个副本,无论我们如何修改这个副本,都不会影响外部值。

void sw(int x, int y) {
    int tmp;
    tmp = x;
    x = y;
    y = tmp;
}

int x = 1;
int y = 2;
sw(x,y);

x  // 1
y  // 2

接下来是指针作为参数的情况。对我们这些初学者来说,尽管读了很多关于指针的大道理,但是面对实际情况时依然会不知所措。这大概就是因为不熟吧~

指针作为参数,说白了就是向函数内部传递目标对象的地址。尽管是以copy的形式把地址传递进去的,但是地址的值是唯一的,也就是说这个地址指向的目标都是货真价实的同一个。并且,凡是参数形式是 func (type* p) 的函数,都是指针传参函数。

void incrementor(int* p)
{
    (*p) ++;
}

int a = 10;
incrementor(&a);

a // 11

在此基础上,有时你可能会会遇到另一种形式的指针参数。 func (type**fuck) 当你遇到它的时候,你可能会问这是什么鬼!!!这东西按行里的话说,叫二级指针. 什么意思呢,我们知道一个对象对应一个内存地址,而地址本身是一个对象结构(目标的地址+类型),它也有一个地址。而 ** 就是指针的指针。当然,顺藤摸瓜你可能联想到三星、四星…子子孙孙无穷尽的情况,这里就不详述了~

二级指针和一级指针的情况类似,一级指针是通过地址来改变目标对象,而二级指针是通过改变地址的指针修修改目标对象的地址,也就是为了修改目标对象的指针。

void my_malloc(int** p){
    //申请一块内存,并赋值给指针对象*p
    *p = malloc(sizeof(int));
}

int *p = 0;
my_malloc(&p);

引用

引用实际上是一个常量指针。表达式 int &i = j;在编译时会被 int *const i = &j; 替换掉。所以,引用在初始化时必须为其赋值。

int& ref = val;

参见

Comments