0.展示PTA总分
1.本章学习总结
1.1指针定义、指针相关运算、指针做函数参数
指针变量不同于整型变量和其他类型的变量,它是专门用来存放地址的,所以必须将它定义为“指针类型”。
基类型 *指针变量名;
比如:int *i; float *j;
地址运算符:&
注解:后跟一个变量名,&给出该变量的地址。
&nurse 表示变量nurse 的地址,输出的是一个十六进制的地址名
间接(或解引用)运算符:*
注解:后跟一指针名或是地址时,*给出储存在指针指向地址上的值。
nurse=22;
ptr=&nurse;//指向nurse的指针
val=*ptr; //把ptr指向地址的值输出并赋值给val
用指针变量作为函数参数, 在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了”通过调用函数使变量的值发生了变化,在主调函数(如main函数)中使用这些改变了值”的目的.
1.2字符指针
字符指针:指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。即将字符串的首地址赋值给字符指针,可让字符指针指向一个字符串。
char *ptr = "Hello";//将保存在常量存储区的"Hello"的首地址赋值给ptr
与
char *ptr;
ptr = "Hello";//是等价的,注意不能理解为将字符串赋值给ptr
char str[10] = "Hello";
char *ptr = str;//数组名代表数组的首地址
//等价于
char *ptr;
ptr = str;//等价于ptr = &str[0];将数组的首地址赋给字符指针ptr
1.3指针做函数返回值
指针值也可以作为函数的返回值。这种情况下函数的返回值类型需要定义成指针变量类型。
返回指针值的函数的一般定义格式为: 数据类型 *函数名称(形式参数列表) 例如: float *Func(float x, float y);
返回值为地址。
1.4动态内存分配
定义数组的长度的时候,必须指定长度,这是在编译期间就要确定的。
当我们无法在编译期间确定到底需要多大的内存块,此时就无法定义数组的大小:
实际使用的元素数量超过了声明的长度,程序无法处理。
如果程序实际使用的元素数量较少,巨型数组会造成内存空间浪费。
此时就需要在运行的时候根据实际的情况(比如根据输入的数据的大小),来动态的申请内存空间,然后让指针指向这块新申请的内存。
malloc和free是库函数,不是系统调用
#include "stdlib.h"
void * malloc(size_t size);
void free(void* pointer);
malloc所分配的是一块连续的内存,参数size是所分配的内存字节数。
malloc的返回值是void* ,具体使用的时候需要做强制类型转换。
当请求的动态内存无法满足的时候,malloc返回NULL,对每个从malloc返回指针都进行检查,确保它不是NULLL。
malloc申请的动态内存中的数据是随机值,不会被初始化为0。
malloc 实际分配的内存可能有会比请求的多。
free的参数要么是NULL,要么是从malloc、calloc、realloc返回的值。
free用于将申请的动态内存归还给系统。
当 free 的参数为 NULL 时,函数直接返回。
calloc函数的参数包含了所需元素的数量以及每个元素的字节数,根据这些值可以计算出一共所需的内存大小。
calloc会将申请的内存空间初始化为0。
如果指向把值存储到数组中,这种操作会浪费一定的时间。
1.5指针数组及其应用
动态内存分配是在堆上进行,需要用户手动分配和销毁
动态内存分配函数需要加上头文件:#include<stdlib.h>
malloc:
原型:void *malloc(unsigned int size)
返回一个通用指针,可以用强制转换的方法将返回的指针值转换为所需的类型
int *pi=NULL;
pi=(int *)malloc(2);
申请2个字节的内存,pi指针变量指向这段存储空间的首地址
pi=(int *)malloc(sizeof(int));用于不能确定某种类型所占内存的字节数
calloc:
原型:void *calloc(unsigned int num,unsigned int size);
第一个参数表示申请空间的数量,第二个参数表示每个空间的字节数
pi=(int *)calloc(10,sizeof(int));
pi=(int )malloc(10sizeof(int));
从安全考虑,前者更好。因为calloc能将分配的内存初始化为0。
free:
原型:void free(void *pi);
形参指向分配的内存地址
1.6二级指针
1.对于一个二级指针进行解引用得到一级指针,对于一个一级指针解引用得到原始变量,int p,*p就是一个指针,p就是原始变量的值。
2.一级指针和二级指针的值都是指向一个内存单元,一级指针指向的内存单元存放的是源变量的值,二级指针指向的内存单元存放的是一级指针的地址
- 二级指针一般用在需要修改函数外部指针的情况。因为函数外部的指针变量,只有通过二级指针解引用得到外部指针变量在内存单元的地址,修改这个地址所指向的内容即可。
int a =1;
int *b =&a;
int **c=&b;
cout<<&a<<endl;
cout<<b<<endl;
cout<<*c<<endl;
/*以上输出都是a的地址,而下面两行就是b的地址*/
cout<<&b<<endl;
cout<<c<<endl;
1.7行指针、列指针
行指针:指的是一整行,不指向具体元素。
列指针:指的是一行中某个具体元素。
可以将列指针理解为行指针的具体元素,行指针理解为列指针的地址。
那么两个概念之间的具体转换是:
*行指针----列指针
&列指针----行指针
2.PTA实验作业
2.1字符串的冒泡排序
我的代码:
同学的代码:
2.2合并2个有序数组
2.3说反话-加强版
此题非常巧妙的运用了栈“先进后出,后进先出”的特性