c语言之指针之谜

变量地址的意义
指针的定义
指针的赋初值
通过指针改变变量的值


内存:(锅)
   A:在计算机中有一个很大的处理场
B:程序都是在内存中运行的
C:总结:数据的处理场地
外存:(电冰箱)数据的存放场地
当我们编写一个c程序,并运行后,它也会放在内存中

什么是指针:
1、c程序要运行,都是在内存中来运行的
2、在c程序中一般会有很多变量,windows就会为程序中的每一个变量分配一个存储单元,
        3、因为内存比较大,为了方便管理windows就会把内存分成很多小块单元,这个单元被称为存储单元。
4、存储单元就是一个小区域
5、存储单元为了以后便于区分,他们也会编址
6、 int a ;
     A:windows马上为这个变量分配一个存储单元
 B:a=5  windows 会马上通过变量名a找到为变量a分配存储单元,然后把值5放入那个单元中去。
 C:以前一直都认为5会把值赋给变量a变量a是不能存储值的,应该是把5放到为a分配的存储单元中
       7、以前都是通过变量名去找到该变量分配存储单元
       8、以前要为变量赋值实际上经过2步
  找变量分配的存储单元(地址)
  再把值写入到那个地址中
      9、把通过变量名找到地址,然后为地址赋值的方式被称为间接方式,效率比较低
    10、 a=a+1
      先从a的地址中读取a的值
  再把值加一后重新写到那个存储单元
    11、指针:
        指针就是地址

指针变量:
   指针变量他是一个变量,,用来存储地址的变量被称为指针变量
这个变量里面以后只能存储地址。而不能存储值

     定义的指针:
            类型标识符 *指针名;  
比如: int *p;
定义了一个指针p以后这个指针变量,只能存储地址,不能存储值。而且它只能存储普通整型变量的地址。
   定义指针的类型标识符:
     他是用来决定指针以后能存储的地址对应的变量的类型
   
给指针赋初值
只能把地址赋给指针
两种方式:
A:在定义的时候赋初值
int a=3,*p=&a;的地址
 B :zai 定义之后,再赋初值
int a=3,*pa;   这里的*是定义时的*
  pa=&a;   指针是pa
  scanf("%d",&a);取地址符
在指针有一个符号非常重要*
1、 根据场合的不同,它的意义也不一样
2、 两种场合:
   A:在定义的时候,*号代表一个标识,表明该变量是一个指针变量
    B:在定义之后,*号就代表指针所指向的变量
       3、 如果把变量a的地址赋给指针p ,那么我们就说,指针p就指向变量a
 int a=3,*pa;
          pa=&a;
          *pa=*pa+1;  //通过指针来改变变量的值的方式,称为直接方式。
          printf("a=%d,*pa=%d",a,*pa);//a=4,*pa=4
4、 几个表达式:
              
       (1)  k=*p++;  	//先把*p的值赋给变量之后 p+1	指针加一,就表示指针会向下移动一个单位
				void main()
				{
				  int a=3,*pa;
                                  pa=&a;
				  k=*pa++;//k=*pa,之后指针pa+1
				  printf("a=%d,k=%d,*pa=%d",a,k,*pa);//a=3,k=3,*pa=不定的值
				}
            				  
		(2)  k=(*pa)++;先把*p的值赋给k,*pa+1
				//相当于k=*pa ,然后*pa=*pa+1
				void main()
				{
				  int a=3,*pa;
                                  pa=&a;
				  k=(*pa)++;//k=*pa,之后指针*pa+1
				  printf("a=%d,k=%d,*pa=%d",a,k,*pa);//a=4,k=3,*pa=4
				}
				
		(3)  k=++(*pa);//先把*p的值加一,之后再把*p的值给k
				相当于*pa=*pa+1 ,然后k=*pa
				void main()
				{
				  int a=3,*pa;
                                  pa=&a;
				  k=++(*pa);//k=*pa+1,之后指针pa+1
				  printf("a=%d,k=%d,*pa=%d",a,k,*pa);//a=4,k=4,*pa=4
				}
		 (4)k=*(++p);  //先把指针p+1之后,再把*p的值赋给变k
			     void main()
				{
				  int a=3,*pa;
                                  pa=&a;
				  k=*(++pa);//z指针pa+1,指针pa就不再指向a, 之后k=*pa
				  printf("a=%d,k=%d,*pa=%d",a,k,*pa);//a=3,k=不定,*pa=不定
				}
5、 谁把变量的地址赋给了指针p,那么p就指向谁
6、 指针p指向变量a,那么*p就相当于a
指针的应用举例

                 main()
		{
			int a=3,b=4,*pa=&a,*pb=&b;//这边的*是定义时的*
		//	*pa=&a;//错了,pa是一个指针,是一个地址,*pa是指针pa指向的变量的值,&a是地址,地址不能赋值给值
		    pb=&a;
			pa=&b;
			*pa=*pb+b;
			*pb=*pa+a;
			printf("a=%d,b+%d,*pa=%d.*pb=%d",a,b,*pa,*pb);//10,7,7,10
		}
				
		 void main()
		{		
			int a=3,b=4,*pa,*pb,*t;	
			pa=&a;
			pb=&b;		
			t=pa;
                        pa=pb;
                        pb=t;
                        *pa=*pb+b;
			*pb=*pa+a;
			printf("a=%d,b+%d,*pa=%d.*pb=%d",a,b,*pa,*pb);//10,7,7,10			
		}		
				
			 void main()
		{		
			int a=3,b=4,c=5,*pa=&a,*pb=&b,*pc=&c;	
			
			pb=&c;
			pc=&a;
                        pa=&b;			
			if(*pa>*pb)
			{
				pb=pc;
			}else
			{
				pa=pb;
			}
                        *pa=*pb+*pc;
			*pb=*pa+*pc;
			*pc=*pa+*pb;
			printf("a=%d,b=%d,c=%d,*pa=%d,*pb=%d,*pc=%d",a,b,c,*pa,*pb,*pc);//			
		}			
总结:
             指针现在指向何方?
             指针是如何进行变化的  
*指针究竟是谁
要使指针指向发生变化,必须要重新把地址赋给指针  p2=p1
要使指针执行*的操作,它变化的是变量的值,而不是指针
*p2=*p1;

int a=3,b=4,*pa=&a,*pb=&b;
pb=pa;
                               pa--->a<----pb 


 以指针作为函数参数
        以指针作为函数参数的格式
1: 整型变量int,实型变量float,字符型变量char都可以作为函数参数
2: 指针实际上是变量,所有指针也可以作为函数的参数
3: 格式:
        类型标识符 函数名(指针)
{
代码;
}
 


例子:
                void fun(int *p)
		{
			if(*p>5)
			{
				*p=*p+1;
			}
			else
			{
				*p=*p-1;
			}
		}
		
		void fun1(int a)
		{
			if(a>5)
			{
				a=a+1;
			}
			else
			{
				a=a-1;
			}
		}
		int sum(int *a,int *b,int *s)
		{
			*s=*a+*b;
		}
		void main()
		{
			int a=2,save;
			fun(&a);//实参把地址传给了型参
			printf("a=%d",a); //a=1
			fun1(a);// 实参把值传给了型参:
			printf("a=%d",a); //a=1
		}
		//
		void sum(int *a,int *b,int *s)
		{
			*s=*a+*b;
		}
		void swap(nt *a,int *b,int *s)
		{
			int t;
			t=*a;
			*a=*b;
			*b=t;
		}
		void main()
		{
			int a=2,b=4,s;
			sum(&a,&b,&s);
			printf("s=%d",s); //s=6
			swap(&a,&b);
		}
		


注意以下几点:
 A:两种传值方式:
    实参把值传给了型参: 传值方式           //型参的改变不会影响实参
 
    实参把地址传给了型参: 传址方式        //型参的改变可能会影响实参
     

        指针作为函数参数的方式
一维数组的指针,指向一维数组的指针

以指针作为函数参数的应用举例

例1:
编写一个函数,用来判断是一个数n是否是质数
        int isPrimer(int *n)
	{
		int i;
		for(i=2;i<n;i++)
		{
			if(*n%i==0)
			return false;
		}
		return true;
		
	}                             //while(n)==while(n!=0)
void main()
{
	int a;
	printf("请输入一个整数:");
	scanf("%d",&a);
	if(isPrimer(int *n))
	{
		printf("是质数);
		
	}else{
		printf("不是质数);
	}
}	
	//写一个函数,求两个数的绝对值的和
	int abs(int *n)
	{
		if(*n>0)
			return *n;
		return -*n;
	}
	int sum(int *a,int *b)
	{
		return abs(*a)+abs(*b);
	}
	
	void main()
	{
		int a=3,b=4,s=0;
		s=sum(&a,&b);
		printf("s=%d",s);
	}



一维数组的指针与指向一维数组元素的指针*********
1、 数组名代表数组的首地址,是常量,常量不能自加 。   变量才能自加 
2、*(a+i)   =a[i] 或a[i]=*(a+i) 只是对于一维数组而言
       *a=a[0]
3、 一维数组名a永远指向a[0],并且不能改变
4、 尽管数组名a是指针,但是这个指针是常量,不能移动,为了能够产生一个可以移动的指针,
   那我们就要定义一个指向一维数组元素的指针(变量)
5、  指针可以比较大小,但只限于在数组中,上面的指针都会比下面的指针小
6、 如何通过指针来访问一维数组的所有元素
for(p=数组名;p<a+数组元素个数;p++)
{
*p就代表数组中的每一个元素

}
只有字符串才有\0  ,整型数组没有
int a[4]={12,34,56,78};                              a-->     a[0]    12            a=&a[0]  数组名本身就是指针
                                                    a+1-->   a[1]    34
                                                    a+2-->   a[2]    56
                                                    a+3-->   a[3]    78   指针指向谁,*指针就等于谁
                                                   *(a+i)   =a[i]  


*(a+i)   =a[i]
    a[i]=*(a+i)



      void main()
	{
		int a[5]={1,2,3,4,5},k1,k2,k3;
		//a是常量,永远不能改变
           k1=*a**a+1;	//1*a[0]+1=2	
	   k2=*a**(a+1);//1*a[1]=2
	   k3=*a*(*a+1);//1*2=2
	   printf("k1=%d,k2=%d,k3=%d",k1,k2,k3);
	}



        void main()
	{
		int a[5]={1,2,3,4,5},*p;//a是常量,永远不能改变         a-->     a[0]
		p=a;        //或者p=&a[0];                             a+1-->   a[1] <--p
        p++;	                                                       a+2-->   a[2]
	                                                               a+3-->   a[3]
	                                                              *(a+i)   =a[i]
	   printf("*p=%d",*p);
	}
	
	
	void fun(flat *a,float *b)
	{
		float w;
		*a=*a+*a;
		w=*a;
		*a=*b;
		*b=w;
	}
	main()
	{
		float x=2.0,y=3.0;
		float *px=&x,*py=&y;
		fun(px,py);
		printf("x=%.1f,y%.1f",x,y);//x=3.0,y=4.0
	}
	
	********************************
		void sub(int x,int y,int *z)
	{
		*z=y-x
	}
	
	
	main()
	{
		int a,b,c;
		sub(10,5,&a);//a=-5
		sub(7,a,&b);//b=-12
		sub(a,b,&c);//c=7
		
		printf("a=%d,b=%d,c=%d",a,b,c);
	}
	
	/***************
		void sub(float x,float *y,float *z)
	{
		*y=*y-1;
		*z=*z+x;
	}
	main()
	{
		float a=2.5,b=9.0,*pa,*pb;
		pa=&a;                         pa--->a(2.5)
		pb=&b;                         pb--->b(9.0)
		sub(a-b,pa,pb);
		printf("a=%.1f",a);//1.5
	}
	
		********************************
		动态数组:就表示在定义数组时,不指定数组的长度,这样这个数组就可以根据赋值的多少,长度动态的发生改变
		
			main()
	{
		int a[]={1,2,3,4,5,6,7,8,9,0},*p;
		p=a;
		printf("%d\n",*p++);//先引用*p的值,然后p再+1,这时p指向a[1]
		printf("%d",*(P+3));      p指向a[4]
		
		key 1
		    *
		
		
	}
	
	
	
	
	main()
	{
		int s[]={1,2,3,4,5,6},*p=s+3;//a[2]=*(a+2)   *(a+i)=a[i]
		printf("%d",p[2]);//6
	}
	
	main()
	{
		int a[]={1,2,3,4,5,6},*p;
		for(p=a;p<a+6;p++)
		{
			printf("%d",*p);
		}
	}





指向一维数组的指针

        main()
	{
		int a[]={2,4,6,8,10},y=1,x,*p;
		p=&a[1];
		for(x=0;x<3;x++)
		{
			y+=*(p+x);//1+4+6+8
		}
		printf("y=%d",y);//19
	}
	
	
	main()
	{
		int a[]={2,4,6,8,10,12,14,16,18},y=1,x,*p;
		p=&a[2];
		
		printf("p[3]=%d",p[3]);//12   p[3]=*(p+3)
	}
	
	
	void sum(int *a)
	{
		a[0]=a[1];       //*(a+0)=*(a+1)
	}
	main()
	{
		int aa[4]={1,2,3,4},i;
		for(i=2;i>=0;i--)
		{
			sum(&aa[i])
		}
		printf("aa[0]=%d",aa[0]);
	}
	void func(int *a,int b[])
	{
		b[0]=*a+6;
	}
	main()
	{
		int a,b[5]={0};
		a=0;
		b[0]=3;
		func(&a,b);
		printf("b[0]=%d",b[0]);
	}
	
	//程序功能,利用指针实现数组a的元素倒置
	void fun(int *x,int *y)
	{
		int t;
		t=*x;
		*x=*y;
		*y=t;
	}
	main()
	{
		int a[8]={1,2,3,4,5,6,7,8},*p,*q,i;
		p=a;
		q=&a[7];
		while(p<q)
		{
			f(p,q);
			p++;
			q--;
		}
		
		for(i=0;i<8;i++)
		{
			printf("%d",a[i]);
		}
		
	}
	
	//把数组a中的所有素数加起来。
	int isPrimer(int *n)
	{
		int i;
		for(i=2;i<n;i++)
		{
			if(*n%i==0)
				return 0;
		}
		return 1;
	}
	
	main()
	{
		int a[10]={11,34,45,56,67,78,89,23,12,32},*p=a,s=0;
		for(;p<a+10;p++)
		{
			if(isPremer(p))
			{
				s+=*p;
			}
		}
		printf("s=%d",s);
	}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aFakeProgramer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值