因为数据保存在存储器中,所以可以根据一个内存单元的编号,准确的找到该内存单元。
内存的编号称为地址或者指针。
int *a = 4;
&a的内容为内存地址,*a是4
注意:
(1)指针类型可以强制转换
int m, *p = &m;
char *p1 = (char*)&m, *p2 = (char*)p;
(2)同类型的指针可以相互赋值
(3)必须谨慎使用指针,一旦使用不当会有灾难性的后果
eg,局部指针变量在定义时其中的值为随机数,即指针指向了一个无意义的地址,也可能偶然指向了一个非常重要的地址。如果对所指的内存进行不当操作,其中的数据就丢失了。
eg,全局指针变量,原指向一个局部变量,后来该内存又重新分配了,再操作,会发生不可预知的错误。
(4)对指针变量绝不可以任意赋一个内存地址,结果真是是灾难性的,
eg,int *p = (int*)0xaf80;
因为不知道这个内存单元存放的什么数据,有可能是系统必要的东西,若不小心改动,也许或造成严重的后果。
(5)常量指针是指向“常量”的指针,即指针本身可以改指向别的对象,但不能通过该指针修改对象。
#include<stdio.h>
int main() {
char c = 'M';
char d = 'R';
const char *p = &c;
printf("c=%c\n", c);
printf("*p=%c\n", *p);
// *p = 'R'; //错误的操纵
// 如果p不是const指针的话,这句话就是对的
p = &d; //正确的操作
printf("c=%c\n", c);
printf("*p=%c\n", *p);
return 0;
}
void类型指针
void指针常用于函数的参数。
当想让一个函数处理多种不同类型的参数时,用void指针
#include<stdio.h>
void half(void *p,char type);
int main() {
int i = 22;
long l = 2222222;
float f = 12.123;
double d = 12.123456;
printf("%d\n", i);
printf("%ld\n", l);
printf("%f\n", f);
printf("%lf\n", d);
half(&i, 'i');
half(&l, 'l');
half(&f, 'f');
half(&d, 'd');
printf("%d\n", i);
printf("%ld\n", l);
printf("%f\n", f);
printf("%lf\n", d);
return 0;
}
void half(void *p, char type) {
switch(type) {
case 'i': {
*((int*)p) /= 2;
break;
}
case 'l': {
*((long*)p) /= 2;
break;
}
case 'f': {
*((float*)p) /= 2;
break;
}
case 'd': {
*((double*)p) /= 2;
break;
}
}
}
数组指针
#include<stdio.h>
int main() {
int arr[5] = {1,2,3,4,5};
int i = 0;
for (i = 0; i < 5; i++)
printf("DS:%X, f[%d]=%d, %d\n", &arr[i], i, arr[i]);
return 0;
}
可以看出,每个数组元素类型都是int型的,占用4个字节。
使用指针变量应该注意的问题
1.指针在使用前必须初始化。
一个数据的地址、地址变量或者空指针NULL。
(1)未被初始化
若未被初始化,指针变量就没有被分配存储空间
int *p;
*p = a;
a被存入一个未知的单元,可能会致错。
(2)错误的初始化,造成程序执行错误或内存空间“丢失”的问题。
int a;
static int *p = a;
因为y是内部auto变量,对应的存储单元随函数的调用而存在,随函数的执行完毕而回收,而静态指针缺长期占用内存。不随函数的执行完毕而释放。
所以用内部auto变量的地址去初始化一个静态指针是没有意义的。
(3)指针初值可以赋值为空值。
2.指针赋值时应该注意的问题
(1)指针的互相赋值造成内存空间的“丢失”。
int *a;
int *b;
a = (int*)malloc(sizeof(int));
b = (int*)malloc(sizeof(int));
*a = 11;
*b = 22;
a = b;
此时的a和b指向同一个内存单元,但是a原来的单元就已经无法访问,已经“丢失”。
解决方法就是,在a=b之前先free(a),释放a的内存单元
(2)给指针变量赋予寄存器的地址,这是不允许的。
register int d;
int *p = &d;
(3)注意别混淆指针和数据。