指针的深入

来源:互联网 发布:初中编程学哪个 编辑:程序博客网 时间:2024/06/05 14:12

指针2

* 开课小练习*

int num = 300;char *p1 = #*p1 = 100;
  • 请问 num的值是多少?

    答案: 300的二级制补码是:// 00000000 00000000 00000001 0010 1100char *p1 :编译器会警告 p1 存储了num的地址*p1 = 100: 二进制补码 ://00000000 00000000 00000001 0110 0100所以char类型 只会读取一个字节的空间 *p1 改变了第一个字节的补码 其他字节没有变化 所以输出后是  353
  • 不管什么类型的指针,都是占用8个字节
  • 分类型:
    • 指针的类型如果不和指向的变量的类型相同的话,那么通过指针就无法确定操作指针的变量
    • 通过指针操作变量时, 指针变量的类型决定了要操作多少个连续字节的空间

多级指针

  • 一级指针:

    • 首先是一个指针, 存储了一个普通变量的地址

      int num = 10;
      itn *p_num = #

  • 二级指针:

    • 首先是一个指针,存储了一个一级指针的地址

      int num = 10;
      itn *p_num = #
      int** pp_num = &p_num;

  • n级指针的使用
int num = 10;int *p_num = #//  一级int **pp_num = &p_num;// 二级int ***ppp_num = $pp_num; // 三级/*打印num的值%d用来输出num%d用来输出*p_num%d用来输出**pp_num%d用来输出***ppp_num*/

指针与整数之间的加减法

  • 我们可以声明1 个指针变量指向数组的元素, 通过指针间接的操作数组的元素
  • 数组名 就是一个地址, 他保存了数组的首地址,也就是数组第0个元素的地址
int arr[] = {10,20,30,40,50,60,70};int *p1 = &arr[0];int *p2 = arr;
  • 遍历数组的三种方式

    • 指针 + 1 ==>指针的值(地址) + sizrof (所有指向元素的数据类型)

      int*类型的指针 0xffff001 + 1 实际上===> 0xfff005

  • 使用指针遍历数组的第一种方式

int arr[7] = {10,20,30,40,50,60,70};int *p1 = &arr;for(int i = 0; i < 7; i++){printf("%d",*(p1+i));}
  • 使用指针遍历数组的第二种方式
int arr[7] = {10,20,30,40,50,60,70};int *p1 = &arr;for(int i = 0; i < 7; i++){printf("%d",*(arr+i));}
  • 使用指针遍历数组的第三种方式
int arr[7] = {10,20,30,40,50,60,70};int *p1 = &arr;for(int i = 0; i < 7; i++){printf("%d",*(p1++));}

使用指针遍历数组的元素的注意点

  • 数组名不能给他重新复制
    • 因为 数组名是一个地址, 这个地址是在定义数组的时候系统分配的
    • 也就是说 数组一旦定义,那么他的地址就是固定的(常量)
    • 所以不能对数组名进行重新复制
  • 指针变量+1的本质
    • 指针变量的值+ sizeof(指针应该指向的数据的类型)
    • 指向的int类型就是地址加 4
  • 指针-1:
    • 指针-1 同等指针加1

数组作为函数参数的本质 中括弧的本质

  • 如果我们为函数写了一个数组作为参数,其实 编译器在编译的时候, 已经把这个数组换成了指针
  • 指针变量后面可以使用中括弧,在中括弧中写下标来访问数据
  • p1[n],前提是p1必须是一个指针
    p1[n]<===> **(p1+n);

  • 式子*(p1+1) 表明

    • 其实 *的后面还可以是一个结果为指针的表达式
    • 只要这个表达式有一个地址值 就可以了
      存储指针的数组
  • 存储指针的数组: 简称 指针的数组(数组指针)
  • 声明格式:
数据类型 *数组名[长度];int num1 = 10;int num2 = 100;int num3 = 1000;//定义一个数组 存储了三个变量int arr[] = {num1,num2,num3};//定义一个数组 存储了三个变量的地址int *p_arr[] = {&num1,&num2,&num3};//或者int *p_arr1[] = {arr,arr+1,arr+2};// 要访问 num1的值printf("num1 = %d\n",num1);printf("num1 = %d\n",arr[0]);printf("num1 = %d\n",*p_arr[0]);

* 指针与指针之间的减法运算*
* 指针相减的意义:
* 代表两个指针指向的变量之间相差多少个单位变量.
* 指针相减的前提 : 这两个指针 必须指向相同的一个数组中的元素
* 公式
* 指针1 - 指针2====> (指针1的值-指针2的值)/sizeof(指针类型)
* 两个指针之间只能做减法
* 指针与指针之间的比较运算*
* 他可以判断两个指针指向的变量的地址 , 谁在高字节 谁在低字节
* 可以判断使用 ==、!=、来判断两个指针指向的地址是不是为同一个地址
* 注意:
* 系统为变量分配地址的时候 是从高字节向低字节分配的
* 变量内部 存储的时候 是从低字节 ===> 高字节

存储字符串数据的两种方式
* C语言中的字符串如何存取
* 使用字符数组:
“`
char name[] = “jack”;
三个长度:
字符串可见长度: 4
字符串实际长度: 5
数组长度: 5

```
  • 注意
    char namr[] = {‘j’,’a’,’c’,’k’};
    不能用%s输出。 因为 从指定的位置开始到‘\0’结束
  • 使用字符指针

    char ch = 'a';
    char *p_ch = &ch;
    char *p_nam = 'jack';
    // 一定要明确:这里并不是把家新款赋值给 p_name
    存储的“jack”这个字符串的首字母的地址

了解内存的5大区域

  • 不同的区域使用来干什么的?为什么区分?
    • 每一个区域都是用来存储数据的
    • 不同区域存储数据 ,方便系统管理
  • 内存中的五大区域

      • 用来存储 局部变量

      • 程序员手动申请内存的存储空间
    • BSS段
      • 未初始化的 全局变量 静态变量
    • 常量区
      • 已经初始化的 全局变量 静态变量 和常量
    • 代码段
      • 存储代码指令 (二进制)

字符串存储的两种方式
* 当他们都是局部变量的时候
* char name1[] = “jack”;
* name1 存储在栈中,”jack“的每一个字符存在字符数组中,也就是栈去
* char *name2 = “rose”;
* name2 存储在栈中,但是rose是存在常量区
* 当他们作为全局变量的时候
* char1[] = “jack”;
* name1存储在存储在常量区 ,jack每一个字符都存储在数组中,也就是常量区
* char *name2 = “rose”;
* name2存储在常量区,”rose“也是常量区。name2这个指针 指向了rose这个字符串的首字母的地址

  • 二者的区别

    char name1[] = "jack";    name1[0] = 'u'; // 可以改 char *name2 = "rose";    name2[0] = 'r'; // 不允许,因为“rose“是一个常量

    字符串的恒定性

  • 以字符指针形式存储字符串
    • 在常量区中 只有一份相同的字符串
  • 难点
    • 第一个

      char *name = "jack"'
      name[0] = 'U';// 这里不更改,想把字符串的额第一个字母改成U是不行的,
      //因为字符串是一个常量 不能修改
      name = "rose"; //这里改的不是jack这个字符串,而是在 name中存储地址,name本来只想的是jack的字符地址,现在只想了 rose
    • 第二个

      char name[] = "jack";
      name[0] = 'U'; //这个可以更改
      name = "rose";
      //这么更改也不行, 因为name是一个数组名存储的是一个地址常量 所以不能更改

字符串数组

  • 字符串数组: 一个数组,每一个元素是一个字符串
  • 如何存储字符串数组

    • 二维的字符串数组

      char name[] = "jack";char[][20] = {"jack","rose","lily","dianli"};
    • 一维指针数组

      char *name[4] = {"jack","rose","lily","dianli"};数组长度:sizeof(数组名) / sizeof(char*);

    * 字符串数组的排序*

 char * countries[] =    {        "Nepal",        "Cambodia",        "Afghanistan",        "China",        "Singapore",        "Bangladesh",        "India",    }// 冒泡排序:for(int i = 0; i < len -1; i++){    for(int j = 0; j < len -1 -i, j++)    {        // 引入 string.h 头文件        int rel = strcmp(countries[j],countries[j+1]);        if(len > 0)        {            //交换两个变量的        }    }}//选择排序for(int i = 0 ; i < len -1; i++){    for(int j = i +1 ; j < len;j++)    {        int rel = strcmp(countries[i],countries[j])            if(rel > 0)            {                //交换的时候                char *temp =countries[i];                countries[i] = countries[j];                countries[j] = temp;            }    }}
0 0
原创粉丝点击