//C指针 

//每一个变量都有一个内存位置,每一个内存位置都定义了可使用**&**运算符访问的地址
//它表示了在内存中的一个地址。
#include<stdio.h>
int main(){
   
	int var_eternity=10;
	int *p;//p指针的类型必须与变量var_eternity的类型一致 
	p=&var_eternity;
	printf("var_eternity变量的地址:%p\n",p);
	return 0;
} 
//指针是一个变量,其值为另一个变量的地址 内存位置的直接地址
//使用前必须声明指针类型

//指针的值的类型都是一个代表内存地址的长的十六进制数

//指针的操作:
//定义一个指针变量;
//把变量地址赋给指针;
//访问指针变量中可用的地址的值。

//通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值
#include<stdio.h>
int main(){
   
	int var=20;
	int *p;
	p=&var;
	printf("var变量的地址:%p\n",&var);
	printf("p变量存储的地址:%p\n",p);
	printf("p变量的值:%d\n",p);
	return 0;
	
} 

//C中的NULL指针
//在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个NULL值是一个良好的习惯
//赋为NULL值的指针被称为空指针
//NULL指针是一个定义在标准库中的值为零的常量
#include<stdio.h>
int main(){
   
	int *ptr=NULL;
	printf("ptr 的地址是:%p\n",ptr);
	return 0;
} 

//内存地址0有特别重要的意义,它表明该指针不指向一个可访问的内存位置 

//C指针的算数运算
//假设ptr是一个指向地址1000的整型指针,是一个32位的整数,让我们对该指针执行下列的算术运算:

ptr++;
//ptr将指向位置1004,ptr每增加一次,它都将指向下一个整数位置,即当前位置往后移4字节
//指向的是存储单元

//递增一个指针

#include<stdio.h>

const int MAX=3;

int main(){
   
	int var[]={
   10,100,1000};
	int i,*ptr;
	ptr=var;
	for(i=0;i<MAX;i++){
   
		printf("存储地址:var[%d]=%p\n",i,ptr);
		printf("存储值:var[%d]=%d\n",i,*ptr);
		ptr++;//指针指向下一个位置 
	}
	return 0;
	
} 

//递减一个指针

#include<stdio.h>

const int MAX=3;

int main(){
   
	int var[]={
   10,100,1000};
	int i,*ptr;
	ptr=&var[MAX-1];
	for(i=MAX;i>0;i--){
   
		printf("存储地址:var[%d]=%p\n",i-1,ptr);
		printf("存储值:var[%d]=%d\n",i-1,*ptr);
		ptr--;//指针指向下一个位置 
	}
	return 0;
	
} 

//指针的比较

//指针可以用关系运算符进行比较,如==、<和>。
//如果p1,p2指向两个相关的变量,比如同一个数组中的不同元素,则可对p1,p2进行大小比较

#include<stdio.h>

const int MAX=3;

int main(){
   
	int var[]={
   10,100,1000};
	int i=0,*ptr;
	ptr=&var[MAX-1];
	while(ptr<=&var[MAX-1])
	{
   
		printf("存储地址:var[%d]=%p\n",i,ptr);
		printf("存储值:var[%d]=%d\n",i,*ptr);
		ptr++;//指针指向上一个位置 
		i++; 
	}
	return 0;
	
} 

//C指针数组
 
#include<stdio.h>

const int MAX=3;

int main(){
   
	int var[]={
   10,100,1000};
	int i,*ptr[MAX];//指针数组
	for(i=0;i<MAX;i++){
   
		ptr[i]=&var[i];
	} 
	for(i=0;i<MAX;i++){
   
		printf("Vaule of var[%d]=%d\n",i,*ptr[i]);
	}
	return 0;
	
} 


//用一个指向字符的指针数组来存储一个字符串列表
#include<stdio.h>

const int MAX=4;

int main(){
   
	const char *name[]={
   "hello","world","ok","thank",};
	for(int i=0;i<MAX;i++){
   
		printf("Value of name[%d]=%s\n",i,name[i]);
	}
	return 0;
} 

//C指向指针的指针

//指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链
//当我们定义一个指向指针的指针时,
//第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置 
int **var;    //声明了一个指向int类型指针的指针;
 
#include<stdio.h>

int main(){
   
	int V;
	int *pt1;
	int **pt2;
	V=100;
	pt1=&V;
	pt2=&pt1;
	
	printf("var=%d\n",var);
	printf("pt1=%p\n",pt1);
	printf("*pt1=%d\n",*pt1);
	pritnf("pt2=%p\n",pt2);
	printf("*pt2=%d\n",*pt2);
	
	return 0;
} 

//C传递指针给函数

#include<stdio.h>
#include<time.h>

void getSeconds(unsigned long *par)
//传递一个无符号的long型指针给函数,并在函数内改变这个值 
{
   
	*par=time(NULL);
	return ;
 } 

int main(){
   
	unsigned long sec;
	
	getSeconds(&sec);
	printf("Number of seconds:%ld\n",sec);//输出实际值 
	
	return 0;
}


//能接受指针作为参数的函数,也能接受数组作为参数
#include<stdio.h>

double getAverage(int *arr,int size){
   
	int i,sum=0;
	double avg;
	for(i=0;i<size;i++)
	{
   
		sum+=arr[i];
	}
	avg=(double)sum/size;
	return avg;
	
} 

int main(){
   
	int balance[5]={
   1,2,3,4,5};//数组 
	double avg;
	avg=getAverage(balance,5);//传递一个指向数组的指针作为参数
	
	printf("Average value is:%.1f\n",avg);
	return 0; 
}

//C从函数返回指针

//C允许从函数返回指针,前提是必须声明一个返回指针函数
int *myFunction(){
   
	...
	...
} 

//c语言不支持在调用函数时返回局部变量的地址,除非定义局部变量为static变量;
//生成10个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回他们;
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

int *getRandom(){
   //要生成和返回随机数的函数 
	static int r[10];
	int i;
	srand((unsigned)time(NULL));//设置种子 
	for(i=0;i<10;i++){
   
		r[i]=rand();
		printf("%d\n",r[i]);
	}
	return r;
} 

int main(){
   
	int *p;//一个指向整数的指针
	int i;
	p=getRandom();
	for(i=0;i<10;i++){
   
		printf("*(p+[%d]):%d\n",i,*(p+i));
	} 
	return 0;
}