课堂笔记
重点内容 1.明白指针背后所蕴含的计算机底层知识 2.熟练掌握指针的简单用法 3.能看懂各种指针操作 4.能够去粉质真的类型与指针指向类型两个概念
指针
指针的重要性 表示一些复杂的数据结构 快速的传递数据 使函数返回一个以上的值 能直接访问硬件 能够方便地处理字符串 是理解面向对象语言中引用的基础
总结:指针式C语言的灵魂
指针的定义 地址 内存单元的编号 从零开始的非负整数 范围:4G【0--4G-1】 指针 指针就是地址,地址就是指针 指针变量就是存放内存单元编号的变量 指针变量是存放地址的变量 指针和指针变量是两个不同的概念 但是要注意,通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样
指针的分类 1.基本类型指针 附注: * 的含义 1.乘法 2.定义指针变量 int * p; //定义了一个名字叫p的变量,int * 表示p只能存放整型变量 3.指针运算符 该运算符放在已经定义好的指针变量的前面 如果是一个已经定义好的指针变量 则* p表示以p的内容为地址的变量 如果通过被调函数修改主调函数普通变量的值 1.实参必须为该普通变量的地址 2.形参必须为指针变量 3.在被调函数中通过 * 形参名 = ...... 的方式就可以修改主调函数相关变量的值
2.指针与数组
指针和一位数组
一维数组名
一维数组名是个指针常量
它存放的是一维数组第一个元素的地址
下标和指针的关系
如果p是个指针变量,则p[i]永远等价于*(p+i)
确定一个一维数组需要几个参数
需要两个参数:
数组第一个元素的地址
数组的长度
指针变量的运算
指针变量不能相加,不能相乘,也不能相除
如果两个指针变量指向的是同一块连续空间中的不同存在
则这两个指针变量才可以相减
一个指针变量到底占几个字节
预备知识:
sizeof(数据类型)
功能:返回值就是该数据所占的字节数
sizeof:(变量名)
功能:返回值就是该变量所占的字节数
假设p指向char类型变量(1个字节)
假设q指向int类型变变量(4个字节)
假设r指向doubla类型变量(8个字节)
p q r 本身所占的字节数
指针和二维数组
3.指针与函数
4.多级指针
专题:
动态内存分配【重点难点】
传统数据缺点:
1.数组长度必须事先制定,且只能是常数量,不能是变量
eg:
int a[5]; // OK
int len = 5; int a[len]; //error
2.传统形式定义的数组,该数据内存程序员无法手动释放
在一个函数运行期间,系统为该函数中数组所分配的空
间会一直存在,知道该函数运行完毕时,数组的空间才
会被系统释放
3.数组的长度一旦定义,其长度不能再改变
数组长度不能在函数运行过程中扩张或缩小
4.A函数定义的数组,在A函数运行期间可以被其他函数利用,
但A函数运行完毕后,A函数中的数组将无法在其他函数使
用
为什么需要动态分配内存
动态内存分配举例_动态数组的构造
静态内存和动态内存的比较
静态内存是系统自动分配的,由系统自动释放
静态内存实在栈分配的
动态内存是由程序员手动分配,手动释放
动态内存是在堆分配
上课程序
基本类型指针
# include <stdio.h>
void swap_l(int i, int j)
{
int t;
t=i; i=j;j=t;
}
int main(void)
{
int a=3,b=5;
swap_l(a,b);
printf ("a = %d, b = %d",a,b);
return 0;
}
# include <stdio.h>
void swap_2(int *p, int *q)
{
int t;
t=*p; *p=*q;*q=t;
}
int main(void)
{
int a=3,b=5;
swap_2(&a,&b);
printf ("a = %d, b = %d",a,b);
return 0;
}
检测实参和形参是否是一个变量
# include <stdio.h>
void f (int i)
{
i = 90;
}
int main (void)
{
int i =6;
printf ("i = %d\n",i);
f(i);
printf("i = %d\n",i);
return 0;
}
指针式函数返回一个以上的值
# include <stdio.h>
int f(int i,int j)
{
return 100;
}
int main(void)
{
int a = 3,b = 5;
a = f(a,b);
b = f(a,b);
printf("%d %d\n",a,b);
return 0;
}
# include <stdio.h>
int f(int * p,int *q)
{
*p = 1;
*q = 2;
}
int main(void)
{
int a = 3,b = 5;
f(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
数组
# include <stdio.h>
int main(void)
{
int a[5];
printf("%#X\n",&a[0]);
printf("%#X\n",a);
return 0;
}
确定一个一维数组需要几个参数
# include <stdio.h>
void f(int*pArr, int len)
{
pArr[3] = 88;
}
int main(void)
{
int a[6] = {1,2,3,4,5,6};
printf("%d\n",a[3]);
return 0;
}
指针变量的运算
# include <stdio.h>
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个单元");
return 0;
}
一个指针变量到底占几个字节的问题
# 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(q), sizeof(r));
return 0;
}
malloc用法
# include <stdio.h>
# include <malloc.h>
void f(int *q)
{
*q = 200;
free(q);
}
int main(void)
{
int *p = (int *)malloc(sizeof(int));
*p = 10;
printf("%d\n",*p);
f(p);
printf("%d\n",*p);
return 0;
}
动态内存分配
# include <stdio.h>
# include <malloc.h>
int main(void)
{
int i;
int len;
int *pArr;
printf("请输入你要存放的元素的个数:");
scanf("%d", &len);
pArr = (int *)malloc(4 * len);
for (i=0; i<len; ++i)
scanf("%d", &pArr[i]);
printf("一位数组的内容是:\n");
for (i=0; i<len; ++i)
printf("%d\n", pArr[i]);
return 0;
}
多级指针
# include <stdio.h>
int main(void)
{
int i = 10;
int *p = &i;
int **q = &p;
int ***r = &q;
printf("i = %d", ***r);
return 0;
}
跨函数使用内容
# include <stdio.h>
void f(int ** q)
{
int i = 5;
*q = &i;
}
int main(void)
{
int *p;
f(&p);
printf("%d\n", *p);
return 0;
}
课后作业
8 8
4 4
0 0
2 2
4
&ref
一维数组的第一个元素的地址
指向下一个地址
a组: 12 16
b组: 12 14
a组: 12 16
b组: 12 14