一、指针
在计算机语言中,由于通过地址能找到所需的变量,可以说地址指向该变量单元,因此把地址形象的称为‘指针’,意思是能通过它来找到以它为地址的内存单元。
1.1、指针&&变量
指针变量与普通变量一样,使用之前不仅要定义说明而且必须要赋具体的值,未经赋值的指针变量不能使用;可以对指针变量初始化为NULL,但是不能对值为NULL的指针变量解引用。
如下定义一个指针变量p指向a,这样就可以通过p访问a并对a进行操作。
int a=0; int *p=NULL; p=&a; *p=10;
指针变量有很多类型,比如int *、char*、float*、void*等等。每种类型的指针可以访问的内存大小不同,如果要访问int类型数据只能使用int*类型指针,以此类推。
void*类型指针,不能对该类型指针进行算法操作,如++和解引用,这是因为void*指向的内存的大小不确定。既然这样,那么void*类型指针到底有什么用呢?
在某些时候,为了提高效率,我们需要一个函数既可以处理int类型,又可以处理char类型,还可以处理其它类型数据,这个时候void*类型就非常有必要了。典型的如内存操作函数。
void * memcpy(void *dest, const void *src, size_t count);
#include <stdio.h> #include <stdlib.h> void*my_memcpy(void*dest, void const*src, size_t count) { char*pdest = (char*)dest; char*psrc = (char*)src; while (count--) { *pdest++ = *psrc++; } return dest; } int main() { int i = 0; int arr[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; my_memcpy(arr + 3, arr, 16); for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { printf("%d ", arr[i]); } printf("\n"); system("pause"); return 0; }
上述代码可以实现数组的移动,移动大小以字节来记。但是memcpy()不处理内存重叠的情况,如果想处理内存重叠应该使用memmove().
上述内容使用的都是一级指针变量,其实还有二级、三级等等指针变量。我们现来看一下二级指针变量,其它以此类推。
int a=10; int *pa=&a; int *ppa=&pa;
指针变量ppa就是一个二级指针变量。上述代码形成的指向关系如下图所示:
变量pa保存的是a的地址,变量ppa保存的是pa的地址;我们可以通过*pa来访问a,同样我们可以通过*ppa来访问pa,那么我们就可以通过 **ppa访问a。也就是说 **ppa就是a,我们可以通过它来操作a。
1.2、指针&&常量
一个常量的地址没有任何意义,我们要讨论的是const修饰的指针。const修饰的指针变量时,这个指针变量便具有了常属性。
1.2.1常量指针
int main() { int a=10; int const *pa=&a;//pa指向的内容不可改 const int *pa=&a; //const放到int左边和右边修饰的都是*pa return 0 }
pa是一个常量指针,const限制了通过这个指针修改变量的值,如果对pa进行 *pa=20;操作,这时编译器会报错,因为const修饰*pa
但是,这并不意味着a不可改,只是不能通过*pa来改而已。我们可以进行如下操作来修改a的值。
int *p=&a; *p=20;
1.2.2指针常量
int main() { int b=10; int *const pb=&b; return 0; }
pb是一个指针常量,指针常量的值是指针,这个值因为是常量,所以它不能被修改.此时pb是一个指针常量,不能在指向其它的变量。如进行以下操作是非法的。
int _b=15; pb=&_b;
虽然pb不可改,并不是说pb指向的内容不可改,如*pb=30;这是可以的。
const 修饰的局部变量仅仅是语法上不可改,其实通过其它变量可以将pb的值改掉,一个指向pb的二级指针,如:
int *ppb=&pb; *ppb=(int*)0x0018ff44;
但是,要注意的是const修饰的全局变量,不管通过什么方法都不可改。因为const修饰的全局变量被存到了只读数据区。
1.2.3指向常量的指针常量
int main() { int c=10; const int *const pc=&c; return 0; }
pc是一个指向常量的指针常量,pc是指针常量,指向的内容也是一个常量,即pc不可改,*pc也不可改。 同样这些并不意味着c的值不可改,只是不能通过*pc来改而已;pc不可改也仅仅是语法上的不可改,如想修改请参照1.2.2。
1.3、指针表达式与运算
不进行运算的指针变量是没有太大的意义的,要使用指针变量进行运算就要知道指针运算的结果和表达式的值。如下所示:
char ch=‘a‘; char cp=&ch;
1.4、使用指针注意事项
- 不能对一个未初始化的指针解引用;
- 不能对一个NULL指针进行解引用;
- 不能向函数传递NULL指针;
- 不能对void*类型指针++和解引用;
C 指针&&表达式&&常量