10、C语言:指针

指针的概念

  • 变量地址:系统分配给变量的内存单元的起始地址
  • 指针:存放另一个变量物理地址的变量,本身也是个变量,也占有物理地址
  • 通过变量名直接寻址
    int k,s;
    scanf("%d",&k);
    s=3*k;
    
  • 通过指针对变量的访问间接寻址
    int *pk;	//定义一个整型指针变量pk
    pk = &k;	//pk所在的内存单元存的是k的内存地址
    printf("%d",*pk);  //*号表示从pk的内存单元中所指的地址中读取内容
    

指针的定义

  • 定义格式:类型标识符 *指针变量名
  • 说明
    1)*号用于定义指针变量,但指针变量名不包括*号
    2)一个指针变量只能指向同一类型的变量
    3)指针变量本身是整型的,指针变量本身也有自己的地址,占四个字节

指针的取值与赋值

  • 取地址运算:用&变量名可以取得该变量的物理地址

  • 取内容运算:用*指针表达式取得指针变量内存单元存储中存的另一个内存地址里的值

  • 给指针变量赋值
    1)指针变量使用前必须要有值
    2)指针变量的数值必须是地址值,不能直接用一个整型赋值
    3)定义格式:int a, *p = &a;int a,*p; p=&a;
    4)可以给指针赋空值,此时指针不指向任何变量:p=NULL;

  • 例子1:用直接方式和间接方式输出变量的值

    #include<stdio.h>
    int main(){
    	int a,b;
    	int *pa,*pb;
    	a = 100;b = 10;
    	pa = &a;pb = &b;
    	printf("%d,%d\n",a,b);
    	printf("%d,%d\n",*pa,*pb);
    	return 0;
    }
    
  • 例子2:将两个整型a和b按由大到小顺序输出——方法1

    #include<stdio.h>
    int main(){
    	int a,b,*p1=&a,*p2=&b,*p;
    	scanf("%d%d",&a,&b);	//5 9
    	if(a<b){
    		p = p1;
    		p1= p2;
    		p2 = p;
    	}
    	printf("%d,%d\n",a,b);	//5,9
    	printf("%d,%d\n",*p1,*pb);// 9,5
    	return 0;
    }
    
  • 例子3:将两个整型a和b按由大到小顺序输出——方法2

    #include<stdio.h>
    int main(){
    	int a,b,*p1=&a,*p2=&b,*p;
    	scanf("%d%d",&a,&b);	//5 9
    	if(a<b){
    		p = *p1;	//将p1所指的内容赋值给p
    		*p1= *p2;		
    		*p2 = p;
    	}
    	printf("%d,%d\n",a,b);	//9,5
    	printf("%d,%d\n",*p1,*pb);// 9,5
    	return 0;
    }
    

指针的算数运算

指针本质也是个变量,在自己的物理地址里存的是别人的物理地址
物理地址是个数字,所以可以对指针进行算数运算

  • 递增一个指针

    #include <stdio.h>
    #define MAX 3
     
    int main ()
    {
       int  var[] = {10, 100, 200};
       int  i, *ptr;
     
       /* 指针中的数组地址 */
       ptr = var;	// 数组名存放的就是首元素的物理地址
       for ( i = 0; i < MAX; i++)
       {
     
          printf("存储地址:var[%d] = %x\n", i, ptr );
          printf("存储值:var[%d] = %d\n", i, *ptr );
          /* 移动到下一个位置 */
          ptr++;
       }
       return 0;
    }
    

    结果如下:

    存储地址:var[0] = bf882b30
    存储值:var[0] = 10
    存储地址:of var[1] = bf882b34
    存储值: var[1] = 100
    存储地址:of var[2] = bf882b38
    存储值:var[2] = 200
    
  • 递减一个指针

    #include <stdio.h>
    #define MAX 3
     
    int main ()
    {
       int  var[] = {10, 100, 200};
       int  i, *ptr;
       /* 指针中最后一个元素的地址 */
       ptr = &var[MAX-1];
       for ( i = MAX; i > 0; i--)
       {
          printf("存储地址:var[%d] = %x\n", i-1, ptr );
          printf("存储值:var[%d] = %d\n", i-1, *ptr );
          /* 移动到下一个位置 */
          ptr--;
       }
       return 0;
    }
    

    结果如下:

    存储地址:var[2] = 518a0ae4
    存储值:var[2] = 200
    存储地址:var[1] = 518a0ae0
    存储值:var[1] = 100
    存储地址:var[0] = 518a0adc
    存储值:var[0] = 10
    
  • 指针的比较
    物理地址本质上也是个整型数,所以也可以比较大小,因此存放地址的指针也可以比较大小

    #include <stdio.h>
    #define MAX 3
     
    int main ()
    {
       int  var[] = {10, 100, 200};
       int  i, *ptr;
     
       /* 指针中第一个元素的地址 */
       ptr = var;
       i = 0;
       while ( ptr <= &var[MAX - 1] )
       {
     
          printf("Address of var[%d] = %p\n", i, ptr );
          printf("Value of var[%d] = %d\n", i, *ptr );
     
          /* 指向上一个位置 */
          ptr++;
          i++;
       }
       return 0;
    }
    

    结果如下:

    Address of var[0] = bfdbcb20
    Value of var[0] = 10
    Address of var[1] = bfdbcb24
    Value of var[1] = 100
    Address of var[2] = bfdbcb28
    Value of var[2] = 200
    

指针与数组

C语言中凡是可以通过数组下标方式完成的操作,都可以用指针的方式实现
例如:利用指针输入和输出数组全部元素

#include<stdio.h>
int main(){
	int a[10],i,*p=a;
	for(i=0;i<10;i++,p++){
		scanf("%d",p);
	}
	printf("\n");
	for(p=a;p<a+10;p++){
		printf("%d ",*p);
	}
	return 0;
}		

存放指针的数组:指针数组

  • 指向整型的指针数组

    #include <stdio.h>
     
    const int MAX = 3;
     
    int main ()
    {
       int  var[] = {10, 100, 200};
       int i, *ptr[MAX];
     
       for ( i = 0; i < MAX; i++)
       {
          ptr[i] = &var[i]; /* 赋值为整数的地址 */
       }
       for ( i = 0; i < MAX; i++)
       {
          printf("Value of var[%d] = %d\n", i, *ptr[i] );
       }
       return 0;
    }
    
  • 指向字符的指针数组

    #include <stdio.h>
     
    const int MAX = 4;
     
    int main ()
    {
       const char *names[] = {
                       "Zara Ali",
                       "Hina Ali",
                       "Nuha Ali",
                       "Sara Ali",
       };
       int i = 0;
     
       for ( i = 0; i < MAX; i++)
       {
          printf("Value of names[%d] = %s\n", i, names[i] );
       }
       return 0;
    }
    

指针与函数

  • 指针变量作为函数参数:将一个变量的地址传送到另一个函数中
    被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值
    1)输出字符串

    #include<stdio.h>
    void display(char *t){
    	char s[] = "Happy";
    	printf("%s\n",t);
    	t = s;
    	printf("%s\n",t);
    }
    int main(){
    	char *p = "Teacher";
    	display(p);
    	printf("%s\n",p);
    	return 0;
    }
    

    2)使用指针实现数组元素逆序存放

    #include<stdio.h>
    void reverse(int *p,int n){
    	int *q,t;
    	for(q=p+n-1;p<q;p++,q--){
    		t=*p;
    		*p=*q;
    		*q=t;
    	}
    }
    int main(){
    	int a[10] = {1,2,3,4,5,6,7,8,9,10};
    	int i;
    	reverse(a,10);
    	for(i=0;i<10;i++){
    		printf("%d ",a[i]);
    	}
    	return 0;
    }
    
  • 数组名作为函数参数
    1)将数组名作为参数传递给函数,本质上就是将数组首元素的地址传递给了函数。
    2)也可以说是一个存着数组首地址的指针传递给了函数,所以本质上和指针变量作为参数是一样的
    3)当用数组名作为参数时,形参数组中元素的值发生改变,实参数组元素中的值也会改变

指针的几种定义方式的区别

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值