指针概念
可以存储地址的变量叫做指针(pointers),存储在指针中的地址通常是另一个变量。“指针”这个词也用于表示一个地址。
类型
每个指针都和某个变量类型相关联,也只能用于指向该类型的变量。一般给定类型的指针写成type*,其中type是给定的类型。
类型void*表示没有指定类型,所以void*可以包含任意类型的数据项地址。void*常常被用作参数类型,或独立于类型的方式处理数据的函数的返回值类型。任意类型的指针都可以传送为void*类型的值,在使用它时,再将其转换为合适的类型。
声明指针
int *p;
int* p;
两种方式,第一种在意义上强调了p是一个指针,第二种在意义上强调p是一个int类型的指针。
通常第二种比较合适,因为一个语句中声明多个指针时 int *p1,*p2,*p3; 比较方便。
使用未初始化的指针非常危险,所以一定要在声明是就初始化。如 int *p=NULL;
运算符
取消引用运算符
*是取消引用运算符,起作用是访问指针指定的地址中存储的数据
int number = 99;
int *p = &number;
*p += 1;
这时候number = 100。
寻址运算符
&是寻址运算符,取变量的地址。用于用已声明的变量地址初始化指针。
int number = 99;
int *p = &number;
指向常量的指针和指针常量
指向常量的指针
int number = 99;
const int *p = &number;
表示p指向一个常量,不能通过p改变该值。
但是可以通过变量本身改变值。指针本身也不是常量,可以改变指针的值。
常量指针
int nubmer = 99;
int *const p = &number;
表示p指向的地址不能改变。
但可以通过p或变量改变变量存储的值。
指向常量的常量指针
int number = 99;
const int *const p = &number;
表示p是一个指向常量的常量指针。
只能通过变量改变存储的值。
如果想让一切都不能被改变,可以在变量number声明时用const。
数组和指针
数值和指针关系密切,有时可以互换。但是它们有一个重要的区别:可以改变指针包含的地址,但不能改变数组名称引用的地址。
一维数组
声明
数组名表示数组中第一个元素的地址。
char s[] = "string";
char *p = &s[0];
和这样声明时等价的
char s[] = "string";
char *p = s;
使用
由于数组索引表示和数组第一个元素的偏移量,所以可以用指针代替数组名。
s[0]和*(p),s[1]和*(p + 1),s[2]和*(p + 2)是等价的。
二维数组
多维数组的名称表示第一个元素的地址,而第一个元素的地址又是该元素的第一个元素的地址。所以s和s[0]和s[0][0]是一样的。
*s表示数组s的第一个元素,s的第一个元素仍然是一个数组,所以还要用*取值。就是**s,表示s[0][0]
(*s+1)表示与数组第一个元素偏移量为 1 的地址,所以还要用*取值。就是*(*s+1),表示s[0][1]
内存使用
头文件
<stdlib.h>
malloc()函数
原型
void* malloc(字节数)
参数
指定需要分配的内存字节数
返回值
返回所分配内存的第一个字节的地址,类型是void*。所以要强制转换成自己所需的类型。
calloc()函数
原型
void* calloc(元素个数,字节数)
参数
数组的元素个数。数组元素占用的字节数。
返回值
返回所分配内存的第一个字节的地址,类型是void*。所以要强制转换成自己所需的类型。
realloc()函数
realloc()函数分配第二个参数指定的内存量,并把第一个指针参数引用的、以前分配的内存内容传递到新分配的内存中,且所传递的内容量是新旧内存区域中较小的那一个。
原型
void* realloc(旧地址,字节数)
参数
包含地址的指针,该地址以前由malloc()、calloc()或realloc()返回。另一个是要分配的新内存的字节数。
返回值
返回所分配内存的第一个字节的地址,类型是void*。所以要强制转换成自己所需的类型。