再探指针

一、指针的操作

(三目运算符 a>b?a:b)

#include <stdio.h>
int main(){
    int a=100;
    int b=200;
    
    a>b?a:b;//判断:若a>b则输出a,否则输出b
    return 0;
}
1.指向常量的指针与指针常量

const char*p;//定义一个指向常量的指针

char *const p;//定义一个指针常量,一旦初始化后其内容不可改变

#include <stdio.h>
int main(){
   /*int x=200;
    int* p=&x;//p指针指向x变量绑定的内存段
  *p=100;//修改p指向内存的内存段中的数据
    printf("%d",x);//结果:输出100
    */
    int x=1086;
    
    //指向常量的指针    值变成常量
    const int* q=&x;
   // *q=52;//会报错
    q=(int*)10086;
    
    //指针常量:不可以改变的指针数据    地址变成常量
    int* const p=&x;
    *p=10;
    //p=10086;//会报错
    
    const int* const p1=&x;//值和地址都不可变
    // *p1=10;报错
   // p1=10086;报错
    
    return 0;
}
2.指针与数组的关系

一个变量有地址,一个数组包含若干个元素,每个元素在内存中都有地址。数组在内存空间的地址是连续的。

指针:变量的首地址

数组的变量名就是数组的首地址

*解引用

#include <stdio.h>
int main(){
   int arr[5]={11,12,45,2,3};
   // printf("%d\n",sizeof(arr));//占20个字节
    
    int* p=&arr[0];//p指向arr[0]这个空间的首地址
    //不能使用int* p=&arr;
    
    int* p1=arr;//数组的变量名就是数组的首地址
    printf("%d\n",*p);//此处结果输出为11
    printf("%d\n",*p1);//*p1解引用,此处结果输出为11
    printf("%d\n",arr[0+1]);//输出数组的第二个数据
    
    printf("----------------\n");
     printf("%#X\n",p);//输出地址相同
     printf("%#X\n",p1);
     printf("%#X\n",arr);
    
    return 0;
}
3.指针运算

指针运算不是简单的整数加减法,而是指针指向的数据类型在内存中占用字节数做为倍数的运算。

char *p;

p++; //移动了sizeof(char)这么多字节

int* p1;

p1++; //移动了sizeof(int)这么多字节

赋值:int *p = &a;

求值:int I = *p;

取指针地址 int **pp = &p;

将一个整数加(减)给指针:p + 3; p – 3;

增加(减少)指针值 p++,p--

求差值 ,p1 – p2,通常用于同一个数组内求两个元素之间的距离

比较 p1 == p2,通常用来比较两个指针是否指向同一个位置。

#include <stdio.h>
int main(){
  
    int x=10086;//int 类型占据4个字节
    //  0000 0000 0000 0000 0010 0111 0110 0110
    //                                        p
    char* p=(char*)&x;//p指向x的最低位
    *(p+3)=128;//使得输出x为负数
    //二进制位负数,最高位是1,
    // 1000 0000 即2^7=128
   
    printf("%d\n",x);
    return 0;
}
4.通过指针使用数组元素

p + 1代表&a[1],也可以直接使用p[1]表示a[5]

p + 5 代表&a[5]

p++

#include <stdio.h>
int main(){
     int arr[5]={11,12,45,2,3};
     int* p=arr;
    
    //for(int i=0;i<5;i++){printf("%d\t",p[i]);}
    // 结果:11      12      45      2       3
    
    double* q=(double*)arr;
    printf("%d\n",*(q+1));
    //q是8个字节,+1是步长移动8个字节,int型数据是4个字节,即数据移动到45
   
    return 0;
}
5.指针数组

指针数组:指向指针的数组

int *p[5];

#include <stdio.h>
int main(){
    int arr[5]={11,12,45,2,3};
      int arr1[7]={1,2,3,4,5,6,7};
     //int* p[5]=arr;//报错
  
    int* p[5];//数组名为p,[5]是5个int类型的指针
    p[0]=arr;
    int i;
	for (i = 0; i < 5; i++) {
		printf("%d\t", p[0][i]);
	}
    printf("\n");
    return 0;
}

//结果输出:11      12      45      2       3
#include <stdio.h>
int main(){
    int arr[5]={11,12,45,2,3};
    int arr1[7]={1,2,3,4,5,6,7};
    
    int* p[5];
    p[0]=arr;
    p[1]=arr1;
    int i;
	for (i = 0; i < 7; i++) {
		printf("%d\t", p[1][i]);
	}
    printf("\n");
    return 0;
}
//结果输出:1       2       3       4       5       6       7
6.指向指针的指针(二级指针)

指针就是一个变量,既然是变量就也存在内存地址,所以可以定义一个指向指针的指针。

  int i = 10;
  int *p1 = &i;
  int **p2 = &p1;
  printf("%d\n", **p2);

以此类推可以定义3级甚至多级指针。C语言允许定义多级指针,但是指针级数过多会增加代码的复杂性,考试的时候可能会考多级指针,但实际编程的时候最多用到3级,但3级指针也不常用,一级和二级指针是大量使用。

7.指向二位数组的指针

数组指针是指针 ,指针数组是数组

int buf3 二维数组名称,buf代表数组首地址
int (*a)[5] 数组指针 行指针 定义一个指向int [5]类型的指针变量a
a[0], *(a + 0), *a 0行,0列元素地址
a + 1 第1行首地址
a[1], *(a + 1) 第1行,0列元素地址
a[1] + 2, *(a + 1) + 2, &a1 第1行,2列元素地址
*(a[1] + 2), ((a + 1) + 2), a1 第1行,2列元素的值
#include <stdio.h>
int main(){
    
    int buf[3][5]={{1,2,3,4,5},
                   {6,7,8,9,10},
                   {11,12,13,14,15}};
    //数组指针又叫行指针,用指针指向二维数组的行号,即(*a)
    int(*a)[5]=buf;//*a=buf[0]  *a+1=buf[1]
    
   //  *a\a[0]\*(a+0)    表示第一行数据
  //   *(a+1)\a[1]        表示第二行数据
    return 0;
}
#include <stdio.h>
int main(){
   int x=10;
    int p=(int)&x;//p指向x的地址
    //修改p的数据
   *((int*)p)=50;//等同于 *(int*)p,括号前加*为解引用
    //(int*)p:p是int 类型的指针,
    
    printf("%d\n",x);//输出结果为50
    return 0;
}
8.指针变量做为函数的参数

函数的参数可以是指针类型。,它的作用是将一个变量的地址传送给另一个函数。

通过函数的指针参数可以间接的实现形参修改实参的值

#include <stdio.h>
void Ch(int x){x=10086;}
int main(){
   int x=100;
    Ch(x);
    printf("%d\n",x);
    return 0;
}//结果输出:100
#include <stdio.h>
void Ch(int* x){
    *x=10086;}//x是一个指针

int main(){
   int x=100;
    Ch(&x);
    printf("%d\n",x);
    return 0;
}//结果输出:10086
9.一维数组名作为函数参数

当数组名作为函数参数时,C语言将数组名解释为指针

int func(int arr[10]);//arr是指针

#include <stdio.h>
void Ch(int x[5]){
    int i;
    for(i=0;i<5;i++){
        *(x+i)=i;}
}

int main(){
  int arr[5]={11,12,45,2,3};
    Ch(arr);
    for( int i=0;i<5;i++){
        printf("%d\n",arr[i]);
    }
    return 0;
}
/*结果输出:
0
1
2
3
4
*/

posted @ 2020-10-26 22:45  星卅  阅读(97)  评论(0)    收藏  举报