指针
指针
指针代表着C语言特定的一个强大的特性,同时也是最让我们害怕的。其中一些畏惧和焦虑来自于在C语言中以一种可笑的荒谬的方式来使用。一般的教程和课程值通过提问学生,让学生解读十分怪异的指针语法组合来讲解指针,很少去在实践中去使用指针。你可能已经看到过许多奇异的指针语法(你将会再次看到),但是,指针没有必要必须要用奇异的难以理解的方式去使用。典型的指针是非常容易理解的。
底线是指针允许你动态分配内存块,你将会使用指针去处理变量,而这些变量都是已经在堆中分配过的。(你可以使用指针去处理栈变量,但是大多数情况下是没有必要的)。
最基本的思想是:一个指针是一个特殊的C数据类型,它包括了一个地址,这个地址指向内存中的某个位置。考虑一个指针就像一个箭头,它指向一块内存区域,而这块内存区域就包含着我们比较感兴趣的实际数据。这不像电话号码的概念,也不像房子地址概念。
指针的目的是允许你手动地直接地区访问一块内存。它在strings和structs中大量使用。我们可以想象通过一个地址在许多块内存中找一个函数(例如一个结构体中包括许多东西),这相比于复制内存块谈后通过这个复制的内存块去访问更加高效,这就是所谓的通过调用传递和通过值传递。下面的例子让你更好的理解.
声明一个指针
这里就是如何声明一个指针
#include <stdio.h>
int main(int argc, const char * argv[]) {
int age = 30;
int *p;
p = &age;
printf("age=%d\n",age);
printf("p=%p\n",p);
printf("p=%d\n",*p);
printf("sizeof(p)=%ld\n",sizeof(p));
*p = 40;
printf("*p=%d\n",*p);
printf("age=%d\n",age);
return 0;
}
输出的结果是:
age=30
p=0x7fff5fbff80c
p=30
sizeof(p)=8
*p=40
age=40
int age = 30这行我们声明了一个int变量age,并且初始化为30,在 p = &age这行,我们声明了一个变量p,它的类型是一个指向int的指针。* 语法是生成一个指针类型去指向另一个类型。通常,你需要声明一个指针去指向一个详细的类型,但是有一个特例就是void指针,它是一个指向未知类型的指针。现在不要担心这种指针。
现在我们有个指针变量p来指向int。到目前为止,它没有指向任何地方。。。我们仅仅声明了一下,想让一个内存空间持有这个指向int的指针。在p = &age,我们给我们的指针p赋值了。我们把另一个变量age的地址赋值给了p。因此现在为止,我们有以下的东西(我们可以在输出中看到):
- age的值是30
- p的值是age变量的地址
- p指向的int有个值30
在输出的第二行,我们可以看到一个很长的数字字符组合字符,它其实是一个16进制的内存地址。
取指针的值
在printf("*p=%d\n", *p);
这一行我们可以看到通过之后怎访问一个值用的是 * 语法。因此p是int的一个地址,反之 * p就是指针指向的int的值。访问指针指向的值就叫做取地址值。
在输出中我们可以看到指针的大小事8个字节。请记住,一个字节8位,因此一个4字节的指针可以达到32位。因此32位指针可以允许我们访问4G的内存。如果我们想超过4G,我们就需要一个更大的指针。在64位操作系统中,指针是8位。
注意一下在 * p = 40发生的事情,我们可以看到最后两行的输出值改变成了40,在*p= 40,,这行,我们使用指针取值去设置指针指向的变量的值(这里设置为了40)。既然p指向的是age这个变量,那么我们将会设置age这个值为40。
指针和数组
当我们使用int vec[5]来声明一个数组的时候,后台究竟发生了什么事情呢?其实后台一块内存被分配(在栈中),这块内存足够去容纳5个整型,vec变量就是一个指针,它指向数组的第一个元素,当你使用这种方式时:printf("vec[2]=%d\n",vec[2]);真正发生的事情是C使用指针算法进入数组,通过适当的次数,然后读取内存中的值。因此,如果你vec数组访问第三个元素,你可以使用vec[2],这个时候C语言开始通过vec的指向开始查找,跳过两个数字,然后取到需要的值(vec[2])。
实现这些最直观的方式就是使用malloc(或者calloc())给数组分配内存(这里在堆中分配),然后通过指针算数去读取值。
malloc和calloc和realloc
他们都是一个函数,作用是在运行时间分配内存,malloc()是根据括号内提供的大小去分配,calloc()和malloc()差不多,但是calloc()还把所有的元素初始化为0.clloc()函数有两个参数,一个是元素个数,另一个是每一个元素的大小。
realloc()可以改变内存的大小。
参考自:http://gribblelab.org/CBootcamp/8_Pointers.html