C语言DAY11 - 指针patr1

来源:互联网 发布:vb soapclient30 编辑:程序博客网 时间:2024/05/16 07:03

    • 指针
          • 变量的地址就叫做指针
      • 指针变量
          • 指针变量也是一个变量存储地址的变量可以间接的访问指向的变量
          • 定义赋值
          • 取地址
          • 操作变量
          • 注意的问题
          • NULL 值
            • 如果没有变量的地址给这个指针变量就初始化一个 NULL代表指针变量不指向内存中的任何地址
          • 多个指针指向同一个变量
            • 函数传递数组
    • int arr 不是传递的这个数组而是这个数组的地址
          • 指针作为函数参数
            • 在函数内部修改实参的值函数只能又一个返回值当需要返回多个值时就可以用指针修改
    • 3 占几个字节连续操作几个字节找到整个变量从而正确有效的操作访问和修改变量
          • 多级指针
          • 指针与整数的加减运算
            • 指针与整数加减运算是在指针地址的基础之上加1个单位变量占用的字节数
          • 指针与数组
          • 使用指针来遍历数组
          • 当数组作为函数的参数的时候
            • 函数如果带了1个参数 这个参数是1个数组
          • 索引的本质
        • 存储指针的数组
        • 指针之间的减法
        • 指针之间的比较运算

指针

变量的地址就叫做指针

指针变量

指针变量也是一个变量,存储地址的变量,可以间接的访问指向的变量.
  • 语法
定义,赋值
数据类型* 指针表变量的名称;int* p1;//类型是 int* 读作 int 指针.double* p2;float* p3;char* p4;1. 只能存储对应类型变量的地址2. 不能赋一个非地址类的数据int* p1 = #//正确的赋值方式

取地址
占位符是%pprintf("%p",&p1)//p1这个变量的地址printf("%p",p1)//p1变量的值,就是*p1指向的变量的地址1.p1 操作的是 p1这个指针变量.2.可以取P1的值,也可以为 p1赋值3.&p1拿到的是 p1的值

操作变量
*p1代表p1指针指向的变量*p1完全等价于 num*p1 = 100;//将100赋值给 numprintf("%d",*p1)//输出 num 的值X 错误的p1 = 200;
注意的问题
1.批量声明int* p1,p2,p3;//这样批量声明p2,p3都是 int 类型//指针类型是*变量名2.野指针int* p1;//指向一块随机的空间,操作起来会出现各种错误//访问的时候,如果随机空间没人用就不会报错,如果有人用就会BAD_ACCESS//如果赋值就相当危险
NULL 值
如果没有变量的地址给这个指针变量,就初始化一个 NULL,代表指针变量不指向内存中的任何地址.
  1. NULL == 0;
    所以也可以直接复制指针变量一个0;
  1. 0代表不指向任何空间
  2. 如果访问一个 NULL 值的指针100%报错.
多个指针指向同一个变量
int num = 100;int* p1 = #int* p2 = p1;//把p1的值赋给了 p2 *p2 也就指向了 num*p2 = 100;

函数传递数组
void test2(int arr[],int len)

//int arr[] 不是传递的这个数组,而是这个数组的地址

指针作为函数参数
void test3(int *p1){    *p1 = 1000;    //函数内部修改变量值}//声明test(&num);//传递对应类型变量的地址执行完函数,num 的值为1000;
  • 有什么作用
在函数内部修改实参的值,函数只能又一个返回值,当需要返回多个值时就可以用指针修改.
int getMaxAndMin(int arr[],int len,int* min);//声明函数int max = getMaxAndMin(arr,sizeof(arr)/sizeof(arr[0]),&min);//调用函数void getZuiDaHeZuiXiao (int arr[],int len,int* pMax,int* pMin);//声明无返回值函数getZuiDaHeZuiXiao(arr,sizeof(arr)/sizeof(arr[0]),&max,&min);//调用无返回值函数,传递两个变量的地址


  • 指针为什么分类型

  1. 变量在内存中不同类型占用不同的字节数指针是最低字节地址
  2. 根据指针类型,确定指向的变量在内存中占用多少字节

> 3. 占几个字节连续操作几个字节找到整个变量.从而正确有效的操作访问和修改变量

多级指针
  1. 一级指针中存储的是1个普通变量的地址.
  2. 二级指针中存储的是1个一级指针变量的地址.
  3. 三级指针中存储的是1个二级指针变量的地址

    • 语法

    一级指针: 数据类型* 指针名;
    二级指针: 数据类型** 指针名;
    int** p2 = p1;
    //这样是错误的,把普通变量的地址赋给了二级指针.
    int** p2 = &p1;
    //这样就把一级指针的地址赋给了二级指针
    //他就指向了一级指针地址中存储的普通变量的地址,
    //就指向了普通变量

    &num == p1
    *p1 == num
    &p1 == p2
    **p2 == num
    *p2 == p1
    &p2 == p3

    • 操作

    int num = 10;
    int* p1 = #
    int** p2 = &p1;

    *p1 = 200;
    //代表 p1指针改变了 num 的值为200.
    (num == 200);

    int age =110;
    *p2 =&age;
    //代表p2这个指针指向的变量,也就是 p1
    //这句话执行完毕,p1就指向 age了
    (*p1 == age)
    同时
    (**p2 == age)

指针与整数的加减运算
指针与整数加减运算,是在指针地址的基础之上加1个单位变量占用的字节数.
int* p1 = #int* p2 = p1+1;//如果 &num 的地址是0x11901,p2的值就是0x11905//不能写成*p1 + 1,这样写就是 num+1了.//*(p1+1)才是正确的表达式
指针与数组
int arr[] = {10,20,30,40,50,60,70};int *p1 = &arr[0];//表示p1指针指向了数组中的第0个元素.int* p2 = arr; //这么做完全也是没有问题,因为arr代表数组的地址.也就是数组的第0个元素的地址.
使用指针来遍历数组.
  1. 第一种方式

    int arr[7] = {10,20,30,40,50,60,70};
    int* p1 = arr;
    //p1指针指向了数组的第0个元素.
    for(int i = 0; i < 7; i++)
    {
    printf(“%d\n”,*(p1+i));
    }

  2. 第二种方式

    int arr[7] = {10,20,30,40,50,60,70};

     for(int i = 0; i < 7; i++) {    printf("%d\n",*(arr+i)); }

    //arr本身就是一个指针地址.

  3. 第三种方式

    int arr[7] = {10,20,30,40,50,60,70};
    int* p1 = arr;

     for(int i = 0; i < 7; i++) {    printf("%d\n",*(p1++)); } *p1 //. 代表p1指针指向的变量. 就是数组中第0个元素.//    *(p1+1);//p1+1 的结果是第1个元素的地址  *(p1+1) 代表数组中第1个元素.//    *(p1+2);//p1+2 的结果是第2个元素的地址. *(p1+2) 代表数组中第2个元素.**注意的地方** 每次循环.p1的值都会变化. 最后1次执行完毕之后. p1指针指向外面去了. p1就不再执行数组中的任何元素了.
    • 注意: 数组名代表数组的地址.而数组一旦创建.数组的地址就确定了.不能改变

      所以.我们不能为数组名赋值. 不能修改数组名的值. 但是可以使用数组名的值.

    结论: 无法修改数组名的值. 不能为数组名赋值.任何值都不可以.

    WHY? 因为数组名代表数组的地址. 而数组一旦创建数组的地址是无法改变的. 所以你不能给他赋值.
    数组名是1个常量.1个地址常量

当数组作为函数的参数的时候
void test(int arr[],int len);//系统在编译的时候已经把数组换成了指针void test(int *arr,int len)//在声明参数的时候,不是创建数组,而是创建一个存储数组地址的指针变量所以 sizeof计算函数参数的长度时永远都是8.
函数如果带了1个参数 这个参数是1个数组.
直接写1个指向数组的第0个元素的指针,=再传入长度
索引的本质
  • 指针变量后面可以使用中括弧,在中括弧中写上下标来访问数据.

    p1[n]; 前提是p1是1个指针变量.

    完全等价于 *(p1+n);

    int num1 = 100;
    int num2 = 200;
    int* p1 = &num2;
    p1[0] == (p1+0) == num2;
    p1[1] == (p1+1) == num1;
    -拿数组举例

    *arr == arr[0];
    *(arr+1) == arr[1];
    1.只要是指针都可以使用中括弧下标.就相当于是去访问指针指向的变量.
    2.操作数组我们虽然使用的中括弧下标来操作,实际上内部仍然使用的指针来操作.

存储指针的数组

  • 声明

    元素类型 数组名[数组长度];
    int* arr[3];
    类是是 int* 长度为3
    int* arr[3] = {p1,p2,p3};
    int* arr[3] = {&num1,&num2,&num3};

    int arr[3] = {10.20,30};
    int* pArr[3] = {arr,&arr[1],&arr[2]};
    *(pArr[0]) = 100;
    //pArr 数组第0个元素是 arr 数组第0个元素的指针,赋值100,arr[0]==100

指针之间的减法

long res = &arr[7] - &arr[1] == 6;指针指向的同一个数组内的两个变量之间相差几个元素

int num1 = 0;double num2 = 0.0;double num3 = 0.0;int num4 =0;int* p1 =&num1;int* p2 =&num4;long res = p2-p1 == 5;double+double+int = 20个字节.//一般只用在同一个数组内,不然结果没有意义.

指针之间的比较运算

  • 比较运算符都可以用在两个指针之间
  1. 变量分配字节空间的时候,从高往低分配.
  2. 比较运算符可以判断两个指针指向的地址谁在高字节谁在低字节. >,>=,<,<=
  3. 也可以用 ==、!=来判断两个指针指向的地址是不是同一个地址.
int* p1 = &num;int* p2 = p1;这个时候 p1,p2都指向同一个变量.
0 0
原创粉丝点击