C语言关于指针的复习整理

一、指针的定义

计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如 int 占用 4 个字节,char 占 用 1 个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就像门牌号、身份证号一样,每个字节的编 号是唯一的,根据编号可以准确地找到某个字节。

我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程 序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF

二、指针变量

1、定义

数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。

int a=1;
int *p;
p=&a;
printf("%d\n", *p); 
printf("%#X, %#X\n", &a, p); 

输出为

1  
0X28FF10 , 0X28FF10 

由第一个输出可以看出,p指向a的地址,利用p可以得到a的取值
%#X 表示以十六进制形式输出,并附带前缀 0X,由输出结果可以看出两者的到相同的值,证明p为指针变量,指向并保存a的地址。

2、取址符、解引用符

定义一个指针变量,应该用 *,然后用 **数据类型+***的格式来定义
int *p

由定义可以看出,要想给指针变量赋值,应该用取地址符“&”:
int *p=&a;
1、指针变量也可以连续定义,例如:

  1. int  *a, *b, *c;

a、b、c 的类型都是 int* 注意每个变量前面都要带*。
2. 如果写成下面的形式,那么只有 a 是指针变量,b、c 都是类型为 int 的普通变量:

   int *a, b, c; 

3、通过指针变量取得数据

int a=1;
int *p;
p=&a;
printf("%d\n", *p); 

输出a=1。
看起来*p和a是等价的,通过 *p 和 a 获取到的数据一样,但它们的运行过程稍有不同:a 只需要一次运算就能够取得数据,而 *p 要经过两次 运算,多了一层“间接”。

4、通过指针变量赋值

1 int a=1;
2 int *p=&a;
3 *p=100;
4 printf("%d\n", a); 

输出 a=100.
第2行代码中 * 用来指明 p 是一个指针变量,第3 行代码中 * 用来给指针指向的数据赋值。

三、数组指针

1、定义

数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元 素在内存中是连续排列的,整个数组占用的是一块内存。
如果一个指针指向了数组,我们就称它为数组指针(Array Pointer)。

 int arr[] = { 1, 2, 3, 4, 5 }; 
 int *p = arr; 

arr 本身就是一个指针,可以直接赋值给指针变量 p。arr 是数组第 0 个元素的地址,因此不用加 &,
也可以写作:

 int arr[] = { 1, 2, 3, 4, 5 }; 
 int *p = &arr[0];
 //也可以改变指针指向
 p=&arr[1] ;

arr、p、&arr[0] 这三种写法都是等价的,它们都指向数组第 0 个元素,或者说指向 数组的开头。
但是“arr 就是一个指针”这种表述并不准确,严格来说应该是“arr 被转换成了一个指针”。

2、用法

如果一个指针变量 p 指向 了数组的开头,那么 p+i 就指向数组的第 i 个元素;如果 p 指向了数组的第 n 个元素,那么 p+i 就是指向第 n+i 个元素。
要记住数组的下标是从零开始的,如果p开始指向的是arr[0],那么p+2指向的是arr[2]
由此得出一些利用下标和指针遍历数组的方法:

  1. 使用下标
    也就是采用 arr[i] 的形式访问数组元素。如果 p 是指向数组 arr 的指针,那么也可以使用 p[i] 来访问数组元素, 它等价于 arr[i]。
  2. 使用指针
    也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(arr+i) 来访问数组元素,它等价 于 *(p+i)。
    如下代码:
 #include <stdio.h> 

 int main()
 { 
    int arr[] = { 99, 15, 100, 888, 252 }; 
     int *p = &arr[0];  //也可以写作  int *p = arr+0;
     //第一种方法
     printf("%d, %d, %d, %d, %d\n", *(p), *(p+1), *(p+2), *(p+3), *(p+4) );
     //第二种方法
     for(int i=0;i<5;i++)
     {
        printf("%d",*(a+i));
      }
      //第三种方法
           for(int i=0;i<5;i++)
     {
        printf("%d",*(p+i));
      }
            //第三种方法
       for(int i=0;i<5;i++)
     {
        printf("%d",*(p+i));
      }
      //第四种
       for(int i=0;i<5;i++)
     {
        printf("%d",p[i]);
      }
    return 0; 
  }

3、关于p++ ,++p, (*p)++

*p++ 等价于 *(p++),表示先取得第 n 个元素的值,再将 p 指向下一个元素,即为将p的地址向后移

*++p 等价于 *(++p),会先进行 ++p 运算,使得 p 的值增加,指向下一个元素,整体上相当于 *(p+1),所以会 获得第 n+1 个数组元素的值。

(*p)++ 就非常简单了,会先取得第 n 个元素的值,再对该元素的值加 1。假设 p 指向第 0 个元素,并且第 0 个元素的值为 99,执行完该语句后,第 0 个元素的值就会变为 100。

4、字符串数组

字符串数组的用法与数组用法类似:

 #include <stdio.h> 
 #include <string.h> 
   int main()
   {
   char str[] = "hello world";
   char *p = str;
    int len = strlen(str), i; 
  for(i=0; i<len; i++){ 
  printf("%c", *(p+i));
     }    
      printf("\n"); 
         //使用p[i]   
      for(i=0; i<len; i++)
      {
     printf("%c", p[i]); 
       } 
          printf("\n");
          //使用*(str+i) 
     for(i=0; i<len; i++)
     {       
      printf("%c", *(str+i));
     } 
     //使用%s输出
     printf("%s\n",p);
     printf("\n"); 
        return 0; 
 } 

除了字符数组,C 语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:
char *str = “hello world”;
或者:
char *str;
str = “hello world”;

四、指针数组

1、定义

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。
一般形式为:

int *p[3];

2、用法

1. #include <stdio.h>
2.  int main(){
3.     int a = 1, b = 22, c = 130;
4.      //定义一个指针数组 
5.    int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *arr[] 
6.   printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
7.  return 0;
8.  } 

arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的 地址对它进行了初始化,这和普通数组类似。
也可以和字符串结合

9. #include <stdio.h> 
10. int main(){ 
11.      char *str[3] = { 
12.          "afdsf", 
13.         "qtedggew",
14.          "wbfdhdn" 
15.      }; 
16.  printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
17.     return 0; 
18.  } 

五、二级指针

1、定义

1. int a =100; 
2.  int *p1 = &a; 
3.  int **p2 = &p1; 
  1. 指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。
  2. C 语言不限制指针的级数,每增加一级 指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级 指针,指向一级指针 p1,定义时有两个*。

2、获取指针数据

想要获取指针指向的数据时,一级指针加一个*,二级指针加两个*,三级指针加三个*,以此类推,
如:

1. int a =100; 
2.  int *p1 = &a; 
3.  int **p2 = &p1; 
4. printf("%d,%d\n",*p1,**p2);

六、指针函数和函数指针

1、指针函数

C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
常用代码形式:

1. #include <stdio.h> 
2.  #include <string.h> 
3.  int *fun1(int x, int y){
4.           x+=y;
5.         return &x;
6.     }
7.  int *fun2(int *x, int* y){
8.      x+=y;
9.  
10.         return x;
11.     }
12. int main(){
13. int m=10,n=20;
14. int *p;
15. p=fun1(m,n);
16. printf("%d\n",*p);
17. p=fun1(&m,&n);
18. printf("%d\n",*p);
19. return 0;
20. }     

用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、 局部数组和形式参数,函数返回的指针请尽量不要指向这些数据, C语言没有任何机制来保证这些数据会一直有效, 因此在调用完该函数后,应该及时使用运行输出。

2、函数指针

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和 数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的 内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。
用法:

1. #include <stdio.h> 
2.  
3.  //返回两个数中较大的一个 
4.  int max(int a, int b){
5.      return a>b ? a : b; 
6.  } 
7.  int main(){ 
8.      int x, y, num; 
9.     //定义函数指针 
10.     int (*pmax)(int, int) = max;  //也可以写作int (*pmax)(int a, int b) 
11.   
12.     scanf("%d %d", &x, &y);
13.      num = (*pmax)(x, y); 
14.      printf("Max value: %d\n",num); 
15.     return 0; 
16.  } 
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值