指针变量
指针是一种特殊的变量,它存储的是某个变量的内存地址。指针变量可以存储内存地址,并且通过指针变量可以间接操作内存中的数据
include <stdio.h>
int main()
{
	int a=1, * p;       //定义指针变量,*是指针运算符
	p = &a;				//把a的地址赋给指针变量p,&是取地址运算符														
	printf("%d\n", *p);	//以整数形式输出指针变量p所指向的变量的值,即a的值							
	*p = 2;				//将整数1赋给p当前所指向的变量,由于p指向变量a,相当于把1赋给a,即a=2	
	printf("a=%d,a的地址是%d",a,p);		//以十进制形式输出指针变量p的值,即输出变量a的地址;a的值变为了2
}
 
通过指针引用数组
数组元素的指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素。
若指针变量直接指向数组变量名,则表示指向数组第一个元素的地址。
int a[10]={1,3,5,7,9,11,13,15,17,19};	//定义a为包含10个整型数据的数组	
int *p = &a[0];		//定义一个整型指针变量,并指向整型数组	
 
int a[10]={1,3,5,7,9,11,13,15,17,19};		
int *p = a;		//等价于int *p = &a[0];	
 
数组元素里指针的运算
在指针已指向一个数组元素时,指针可以进行以下运算:
- p+1:表示指向同一数组的下个元素
 - p-1:表示指向同一数组的上个元素
 - p++,p–:指针的自加自减运算
 
若p的初值是a(即&a[0]),则p+i和a+i就是数组元素a[i]的地址,它俩指向a[i]
*(p+i)或*(a+i)是p+i或a+i指向的数组元素值,即a[i]
include <stdio.h>
int main()
{
	int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int *p = a;
	//下述三个输出结果均为2
	printf("%d", *(p + 2));
	printf("%d", *(a + 2));
	printf("%d", a[2]);
}
 
通过数组名作函数参数
以变量名和数组名作为函数参数的比较

int main()
{	void fun(int arr[], int n);	//对fun函数的声明
	int array[10];			//定义array数组
	   ⋮
	fun(array,10); 			//array是实参,arr是形参,
	return 0;
} 
void fun (arr[ ],int n)   
{	printf(″%d\n″, *arr);		//输出array[0]的值
	arr=arr+3;			//形参数组名可以被赋值
	printf(″%d\n″, *arr);		//输出array[3]的值
}
 

通过指针引用字符串
字符串的引用方式
/*通过定义字符串数组*/
include <stdio.h>
int main()
{	char string[]="I love China!";	//定义字符数组string
	printf("%s\n",string);		//用%s格式声明输出string,可以输出整个字符串
	printf("%c\n",string[7]);		//用%c格式输出一个字符数组元素,输出'C'
	return 0;
}
 
字符串指针作函数参数
将字符串指针作为函数参数, 有以下四种传递方式
| 实参 | 形参 | 
|---|---|
| 字符数组名 | 字符数组名 | 
| 字符数组名 | 字符指针变量 | 
| 字符指针变量 | 字符指针变量 | 
| 字符指针变量 | 字符数组名 | 
下述代码用于实现字符串拷贝
include <stdio.h>
int main()
{	void copy_string(char from[], char to[]);	//函数声明
	char a[]="I am a teacher.";		//定义字符数组a并初始化
	char b[]="You are a student.";	//定义字符数组b并初始化
	char *from=a,*to=b;	//from指向a数组首元素,to指向b数组首元素 
	printf("string a=%s\nstring b=%s\n",a,b);
	printf("copy string a to string b:\n");
	copy_string(from,to);	//实参为字符指针变量
	printf("\nstring a=%s\nstring b=%s\n",a,b);
	return 0;
}
void copy_string(char from[], char to[]) 		//形参为字符数组
{	int i=0;
	while(from[i]!='\0')
	{	to[i]=from[i]; i++;}
	to[i]='\0';
}
 
指向函数的指针
什么是函数的指针
函数名就是函数的指针,它代表函数的起始地址。
函数指针变量调用函数
/*判断两数的大小*/
include <stdio.h>
int main()
{	int max(int,int);	//函数声明
	int (*p)(int,int);	//定义指向函数的指针变量p,表示指向函数类型为整型且有两个整型参数的函数
	int a,b,c;
	p=max;			//使p指向max函数
	printf("please enter a and b:");
	scanf("%d,%d",&a,&b);
	c=(*p)(a,b);		//通过指针变量调用max函数
	printf("a=%d\nb=%d\nmax=%d\n",a,b,c);
	return 0;
}
int max(int x,int y)		//定义max函数
{	int z;
	if(x>y)z=x;
	else z=y;
	return(z);
}
 
指针数组
什么是指针数组
一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。
如下代码定义了一个指针数组, 用于存放int类型的指针元素
int *p[4]; 
 
使用实例
include <stdio.h>
int main()
{
	int a[5] = { 1,3,5,7,9 };
	int* num[5] = { &a[0],&a[1],&a[2],&a[3],&a[4] };
	int** p, i;				//p是指向指针型数据的指针变量
	p = num;				//使p指向num[0],即p指向&a[0]
	for (i = 0; i < 5; i++)
	{
		printf("%d ", **p);  //*p=&a[0]  **p=a[0]
		p++;
	}
	printf("\n");
	return 0;
}
 
动态内存分配
定义
全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的
除此以外,C语言还允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为堆(heap)。可以根据需要,向系统申请所需大小的空间。
由于未在声明部分定义它们为变量或数组,因此不能通过变量名或数组名去引用这些数据,只能通过指针来引用
动态分配内存的函数
malloc函数
该函数是一个指针型函数,返回的指针指向该分配域的第一个字节
/* void *malloc(unsigned int size); */
int *p = malloc(100);   //开辟100字节的临时分配域,函数值为其第1个字节的地址;若函数执行失败(如内存空间不足),则返回空指针(NULL)
 
calloc函数
在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。
/* void *calloc(unsigned n,unsigned size); */
p=calloc(50,4);		//开辟50×4个字节的临时分配域,把首地址赋给指针变量p;若执行失败返回NULL
 
realloc函数
如果已经通过malloc函数或calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配。
/* void *realloc(void *p,unsigned int size) */
realloc(p,50);	//将p所指向的已分配的动态空间改为50字节;失败则返回NULL
 
free函数
是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值
free(p); //释放指针变量p所指向的已分配的动态空间,无返回值
 
使用实例
建立动态数组,输入5个学生的成绩,另外用一个函放数检查其中有无低于60分的,输出不合格的成绩
include <stdio.h>
include <stdlib.h>				//程序中用了malloc函数,应包含stdlib.h
int main()
{
	void check(int*);				//函数声明
	int* p1, i;						//p1是int型指针
	p1 = (int*)malloc(5 * sizeof(int));	//开辟动态内存区,(int *)表示强制指针类型转换
	for (i = 0; i < 5; i++)
		scanf("%d", p1 + i);			//输入5个学生的成绩 
	check(p1);					//调用check函数
	return 0;
}
void check(int* p)					//定义check函数,形参是int*指针
{
	printf("They are fail:");
	for (int i = 0; i < 5; i++)
		if (p[i] < 60) printf("%d \0", p[i]); 	//输出不合格的成绩 
	
}
 
指针总结
| 变量定义 | 含义 | 
|---|---|
int i | 定义整型变量i | 
int *p | 定义p为指向整型数据的指针变量 | 
int a[5] | 定义整型数组a,它有5个元素 | 
int *p[4] | 定义指针数组p,它由4个指向整型数据的指针元素组成 | 
int (*p)[4] | p为指向包含4个元素的一维数组的指针变量 | 
int *p() | p为返回一个指针的函数,该指针指向整型数据 | 
int (*p)() | p为指向一个返回值为整数的函数的指针 | 
int **p | p是一个指针变量,它指向一个指向整型数据的指针变量 | 
void *p | p是一种指向任意类型数据的通用指针。它可以指向任意类型的数据,但是不能通过该指针直接访问数据,需要先转换为特定的指针类型再访问 | 



















