本文是郝斌老师《C语言自学教程》指针部分的总结,强烈推荐大家去看原教程
第一个指针程序(入门)
#include <stdio.h>
int main()
{
int *p;
int i=3;
p=&i; //&为取地址符
return 0;
}
针对上述程序:
1.如何理解 int*p
?
int*p
不表示定义了一个名字叫做*p
的变量.int*p
变量的名字是p
,类型是int*
,是指实际存放int类型变量的地址,即p变量
存放的是int类型变量的地址
2.可不可以出现 p=i;
?
不可以 p存放的是int类型变量的地址,不能存放int类型变量
3.如何理解p=&i
;?
- p保存了i的地址,因此p指向i
- p不是i,i也不是p
- 修改p的值不影响i的值,修改i的值也不影响p的值
- 如果一个指针变量指向了某个普通变量,则
*指针变量
=普通变量
例如:
如果p
是个指针变量,并且p
存放了普通变量i
的地址,则p
指向了普通变量i
,那么*p
完全等同于i
. 换句话说,在所有出现*p
的地方都可以替换成i
,在所有出现i
的地方都可以换成*p
*p
就是以p
的内容为地址的变量 (p指向i,p的内容就是i的地址,以i的地址为地址的变量就是i自身)
小测试:
int main() {
int i=3;
int j;
int *p=&i;
j=*p; //等价于j=i;
printf("i=%d,j=%d",i,j);
}
指针
1.什么是指针?
指针就是地址,地址就是指针
地址:内存单元的编号 ,从零开始的非负整数
指针的本质就是一个操作受限的非负整数,两个指针之间只能进行减法运算,不能进行乘除加法运算
2.指针和指针变量的区分
-
指针就是地址,地址就是指针
-
指针变量就是存放地址的变量
-
指针和指针变量是两个不同的概念,但是通常我们叙述时,会把指针变量简称为指针,实际它们的含义并不一样
3.指针的作用
-
用来表示一些复杂的数据结构
-
快速传递数据
-
使函数返回一个以上的值
-
能直接访问硬件
-
能够方便地处理字符串
-
是理解面向对象语言中引用的基础
总结:指针是C语言的灵魂
C语言中*
的含义:
-
做乘法
-
定义指针变量
int *p
定义了一个名字叫p
的变量,int *
表示p
只能存放int
类型变量的地址 -
指针运算符(解引用)
该运算符放在已经定义好的指针变量前面,如果
p
是一个已经定义好了的指针变量,则*p
表示以p的内容为地址的变量
指针和一维数组
一维数组:一维数组名是一个指针常量,它存放的是一维数组的第一个元素的地址
数组下标和指针的关系: a[i]=*(a+i)
例如:
#include<stdio.h>
int main(){
int a[5]={1,2,3,4,5};
//a[3]=*[a+3];
printf("%d\n",a[3]);
printf("%d\n",*(a+3));
printf("%d\n",3[a]);
}
1.指针变量的运算
假设指针变量的名字为p,则
p+i的值是p+i*(p所指向的变量所占的字节数)
p-i的值是p-i*(p所指向的变量所占的字节数)
p++=p+1;
p--=p-1;
指针不能相加,不能相乘,不能相除
如果指针变量属于同一数组(同一块连续空间中的不同存储单元),则可以相减
2.指针变量所占字节数
一个指针变量,无论它指向的变量占用几个字节,该指针变量只占用4个(32位系统)或8个字节(64位系统)
64位系统, 64位计算机有64根地址线,每根地址线要么是0要么是1,只有两种状态。内存单元中的每个地址都是由着64根地址线通过不同的状态组合而成的,而8字节刚好64位,正好能存储下所有内存单元的地址信息,32位系统同理.
疑问?
指针只记录某个变量首个内存单元的地址,那指针是如何知道某个数据类型到底占用几个内存单元的呢?
例如: int 占用4个字节 double占用8个字节 int*
和double*
只记录int和double类型数据的第一个字节的地址信息,那指针是如何知道int和double分别需要使用4个和8个内存单元才能完整储存一个数据?
根据指针自己本身的数据类型确定
动态内存分配(malloc函数)
#include<stdio.h>
#include<malloc.h>
int main(){
int i=5;//静态内存分配
int *p=(int*)malloc(sizeof(int));
free(p);//free(p)表示把p所指向的内存给释放掉 ,p本身的内存是静态的,p本身的内存只能在p变量所在的函数运行结束时由系统自动释放
*p=5;//*p代表一个int变量,只不过这个int变量的内存分配方式和i不同,是动态分配
}
针对上述程序:
1.要使用malloc函数,必须添加malloc.h这个头文件
2.malloc函数只有一个形参,并且是整型
3.形参表示为为本程序分配几个字节
4.malloc函数只能返回第一个字节的地址
5.强制类型转换的意义是把分配完的空间按照几个字节为一组进行划分,每一组用来存储一个数据(同上述疑问?)
跨函数使用动态内存示例
#include<stdio.h>
#include<malloc.h>
void f(int** q){
*q=(int*)malloc(sizeof(int));//等价于p=(int*)malloc(sizeof(int);
**q=5;//等价于*p=5;
}
int main(){
int *p;
f(&p);
printf("%d\n",*p);
return 0;
}