指针
-
指针就是地址,地址就是指针
-
地址就是内存单元的编号
-
指针变量是存放地址的变量
-
指针和变量是两个不同概念
-指针本质就是一个操作受限的非负整数
1.指针的重要性
-
表示一些复杂的数据结构
-
快速的传递数据
-
使函数返回一个以上的值
-
能直接访问硬件
-
能够方便的处理字符串
-
是理解面向对象语言中引用的基础
总结:指针是C语--言的灵魂(十分重要)
2.指针的定义
-
地址
- 内存单元的编号
- 从零开始的非负整数
- 范围:4G
3.指针的分类
- 基本类型指针
#include <stdio.h>
int main (void)
{
int *p;//p是变量的名字,int *p表示变量存放的是int类型变量的地址
//int * p;不表示定义了一个名字叫做*p的变量
//int * p;应该这样理解;p是变量名,p变量的数据类型是int *类型
// 所谓int *类型实际就是存放int变量地址的类型
int i = 3;
int j;
p = &i;
/*
1.p保存了i的地址,因此p指向i
2.p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值不影响p
3.如果一个指针变量指向了某个普通变量,则
*指针变量 就完全等于 普通变量
例子:
如果p是某个指针变量,并且p存放了普通变量i的地址
则p指向了普通变量i
* p 就完全等同于 i
或者说:在所有出现*p的地方都可以替换成i
在所有出现i的地方都可以替换成*p
/*
j = *p;
printf("i = %d,j = %d\n",i,j);
return 0;
}
附录: *的含义
1.乘法
2.定义指针变量
1.乘法
2.定义指针定量
- int p;//定义了一个名字叫p的变量,int表示p只能存放int变量的地址
3.指针运算符
-
该运算符放在已经定义好的指针变量的前面
-
如果p是一个已经定义好的指针运算
-
则*p表示以p的内容为地址的变量
如何通过被调函数修改主调函数的值
-
1.实参必须为该普通变量的地址
-
2.形参必须为指针变量
-
3.在被调函数中通过
形参名=.....
的方式就可以修改主调函数相关变量的值
指针和数组
-
指针和一维数组
-
一维数组名
-
一维数组名是个指针常量
-
它存放的是一维数组第一个元素的地址
-
-
下标和指针的关系
-如果p是个指针变量,则
p[i]永远等价于*(p+i)
- 确定一个一维数组需要几个参数【如果一个函数处理一个一级 数组需要两个参数:
1.数组第一个元素地址
2.数组的长度
-
指针变量不能相加,不能相乘,也不能相除
-
如果两个指针变量指向的是同一块连续空间中不同的存储单元,则这两个指针变量才可以相减(代码在后面)
*p q r本身所占的字节数是否一样*
* 一个指针变量到底占几个字节*
- 假设p指向char类型变量(一个字节)
- 假设q指向int类型变量(四个字节)
- 假设r指向double类型变量(八个字节) 预备知识: 1.sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数
例子:sizeof(int) = 4
sizeof(char) = 1
sizeof(double) = 8
sizeof(变量名) 功能:返回值是该变量所占的字节数
总结:
一个指针变量,无论它指向的变量占几个字节该指针变量本身只占四个字节
一个变量的地址使用该变量首字节的地址来表示
-
指针和二维数组
-
多级指针:
-
int i = 10;int * p=&i;//p只能存放int类型变量的地址
-
int q = &p;//q是int类型,所谓的int**类型就是指q只能存放int*类型变量的地址
-
int*** r = &q;
printf(“i = %d\n",***r); 3.指针和函数
-
-
4.指针和结构体
5.多级指针
专题:动态内存分配
-
传统数组的缺点:
- 数组长度必须事先制定,且只能是常整数,不能是变量
例子:
int a[5];//ok int len = 5;int a[len];//error-
传统形式定义的数组,该数组的内存程序员无法手动释放,数组一旦定义,系统为该数组分配的存储空间就会一直存在,直到该函数运行完毕时,数组的空间才会被系统释放
-
数组的长度一旦定义,其长度就不能再更改数组的长度,不能在函数运行的过程中动态的扩充或缩小
-
A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A函数中的数组将无法再被其他函数使用
*传统方式定义的数组不能跨函数使用
-
为什么需要动态分配内存?
答:动态数组很好的解决了传统数组的这四个缺陷
传统数组也叫静态数组
-
动态内存分配距离-动态数组的构造
-
静态内存和动态内存的比较
-静态内存是由系统自动分配,由系统自动释放
-
跨函数使用内存的问题
代码实操
1.指针经典互换
#include<stdio.h>
void huhuan(int *p, int *q)
{
int t;
t = *p;
*p = *q;
*q = t;
return;
}
int main(void)
{
int a = 3;
int b = 5;
huhuan(&a,&b);
printf("a = %d, b = %d\n",a,b);
return 0;
}
2.确定数组
#include <stdio.h>
void f(int * pArr,int len)
{
int i;
for (i = 0;i<len;i++)
printf("%d ", pArr[i]);
//pArr[i]
printf("\n");
}
int main(void)
{
int a[5] = {1,2,3,4,5};
int b[6] = {-1,-2,-3,4,5,-6};
int c[100] = {1,99,22,33};
f(a,5);
f(b,6);
f(c,100);
return 0;
}
3.指针相减
int main(void)
{
int i = 5;
int j = 10;
int * p = &i;
int * q = &j;
int a[5];
p = &a[1];
q = &a[4];
printf ("p和q所指向的单元相隔%d个单元\n",q-p);
return 0;
}
4.指针字节问题
#include<stdio.h>
int main(void)
{
char ch = 'A';
int i = 99;
double X = 66.6;
char * p = &ch;
int *q = &i;
double * r = &X;
printf("%d %d %d\n",sizeof(p),sizeof(r));
return 0;
}
5.malloc的使用
malloc 是memory(内存)allocate(分配)的缩写
*/
#include <stdio.h>
#include<malloc.h>
int main(void)
{
int i = 5;//分配了4个字节,静态分配
int*p = (int *)malloc(4);
/*
1.要使用malloc函数,必须添加malloc.h这个头文件
2.malloc函数只有一个形参,并且形参是整型
3.4表示请求系统为本程序分配4个字节
4.malloc函数只能返回第一个字节的地址
5.5行分配了8个字节,p变量占4个字节,指向的内存也占着四个字节
6.p本身
*/
free(p);//free(p)表示把p所指向内存给释放掉了,p本身的内容是静态的,不能由程序释放
printf("同志们好!\n");
return 0;
}
6.动态一维数组的使用
#include <malloc.h>
int main(void)
{
int a[5];
int len;
int * pArr;
int i;//动态的构造一维数组
printf("请输入你要存放的元素的个数:");
scanf("%d",&len);
pArr = (int *)malloc(4 * len);//第12行 本行动态构造了一个一维数组
//对一维数组进行操作进行操作
for (i = 0;i < len;++i)
scanf ("%d",&pArr[i]);
//对一维数组进行输出
printf("一维数组的内容是:");
for (i = 0;i<len;++i)
printf ("%d\n" , pArr[i]);
return 0;
}
习题作业
-
8 8 4 4 0 0 2 2 -
4 -
&ref 一维数组的第一个元素的地址 指向下一个地址 -
a组:12 16 b组:12 14 -
a.12 16 b.12 16