C语言指针与数组

目录

数组内存地址

指针 + 偏移

指针加减法

指针变量遍历数组


数组内存地址

  • 数组是内存中一块连续的空间
       // 取一个变量的地址 &符号;
       int a = 4; // &a取得变量A的内存地址;
       // 数组是一块连续的内存,类型 名字[个数]
       // sizeof(类型) * 个数,连续的内存;
       // 局部变量的数组,所以这个数组的内存是分配在我们的栈上的
       // 连续的内存,由低地址排到高地址;
  • 操作数组地址的方法
  1.  名字为这块内存的首地址   ------>   名字 + offset,就可以确定元素的地址位置
  2. 数组元素取地址   ------>   &名字[offset]
       int b[3] = {1, 2, 3};
       /* 数组的内存地址:
       数组元素的内存地址,第2个元素的内存地址
       (1)&(数组名字[索引]),数组的开始(首)地址,&数组名字[0];
       (2)数组名字本身就是一个地址,它是这个数组的首地址;
       int b[3]; b就是这个数组的内存起始地址,b == &b[0];
       (3)使用数组名字+偏移offset,来获取从数组的首地址到offset这个元素的地址;
       int b[3]; int offset = 2; b + offset 相当于 &b[offset], 数组内存的首地址;
       */
       printf("0x%x, 0x%x\n", b, &b[0]);
       int offset = 2;
       printf("0x%x, 0x%x\n", b + offset, &b[offset]);
       //  观察一下 b, b + 2 --> 8个字节 --> offset * sizeof(int);
       // offset指的是数组元素的个数,
       // b + offset的数值大小其实是: b + sizeof(数据类型) * offset;
       // offset不是指的字节数,而是元素的个数;
       // end
  • 二维数组:(二维数组是按照每一行每一行的存储,内存里面就是连续的1维数组)
  1. 二维数组的名字为二维数组的首地址
  2. a[y] 表示是第y行的地址
  3. &a[i][j]   ------>   元素(i,j )的地址
       //  二维数组,
       // 二维数组其实也是一维数组,它是数据元素一行一行的存到内存里面的;
       int s_array[3][3] = {
              { 0, 1, 2, },
              { 10, 11, 12, },
              { 20, 21, 22, },
       };
       /*
       二维度数组地址:
          (0)二维数组每一个元素来取地址;
          (1)二维数组的名字,就是二维数组的首地址--> &s_array[0][0]
          (2)二维数组每行的地址: s_array[行数] --> &s_array[行数][0]
       */
       printf("===============\n");
       printf("0x%x, 0x%x, 0x%x\n", s_array, &s_array[0][0], s_array[0]);
       printf("0x%x, 0x%x\n", s_array[1], &s_array[1][0]);
       printf("===============\n");
       // end

指针 + 偏移

  • 指针变量指向数组中的内存地址
  • 指针+偏移的方式访问内存
  1. *(p + offset)
  2. p[offset]
       // *指针变量, 访问指针变量里面存放的内存地址的内存数据
       // 存放地址的变量;
       p = b; // *p --> p内存地址,内存数据,
       printf("%d, %d\n", *p, b[0]);
       p = b + 1; // p 存放的是数组第1个元素地址;
       printf("%d, %d\n", *p, b[1]);
       p = &b[2];
       printf("%d, %d\n", *p, b[2]);
       // end

       // *指针变量, 指针变量[offset];
       // 指针变量[offset]:访问的是从这个指针保存的地址开始,偏移offset个元素(sizeof(类型))的内存数据;
       // 以指针变量为内存基地址(开始地址) 偏移offset个元素(不是字节);
       // 为什么数组的索引是从0开始的,因为数组的名字表示的是首地址,而最开始的元素,就是从首地址开始存的,所以偏移是0;

       p = b;
       printf("%d, %d\n", p[0], b[0]);

指针加减法

  • p  = p + offset 指针加法是向后移动offset个元素的地址   ------>   注意不要越界,不要访问非法的内存区域
  • p = p - offset 指针向前移动offset个元素
  • p ++, p --   ------>   简洁
       // 指针的加;
       // p + offset, 是以p为首地址,然后正向偏移offset个元素(不是字节)的地址
       // 数值上 p保存的内存地址 + offset * sizeof(数据类型);
       p = b;
       printf("b[1]的地址 0x%x, 0x%x, 0x%x\n", p + 1, &b[1], b + 1);

       // *(指针变量 + offset) 来访问我们的内存数据;
       printf("b[2]: %d, %d, %d\n", *(p + 2), p[2], b[2]);

       // *(数组名字 + offset)来访问我们的内存数据;
       printf("b[2]: %d, %d, %d\n", *(b + 2), p[2], b[2]);
       // end

       // 指针减: p - offset向前挪动offset个元素()
       p = b + 1; // p指向了数组的第1个元素的地址;
       printf("b[0]: %d, %d\n", b[0], *(p - 1));
       // 指针和数组,不要越界,包保正使用指针访问的每一个内存是合法的;
       // end

指针变量遍历数组

  • 指针变量来遍历一维度数组
  • 指针变量遍历二维数组
       p = b;

       for (int i = 0; i < 3; i++, p++) {
              printf("%d, %d, %d\n", *p, p[0], *(p + 0));
       }
       p = s_array;
       for (int i = 0; i < 3; i++) {
              for (int j = 0; j < 3; j++) {
                     printf("%d ", *p);
                     p++;
              }
              printf("\n");
       }
       // 指针每次保存二维数组的每行的地址
       p = s_array;
       // 有多少行
       for (int i = 0; i < 3; i++) {
              // 每一行循环遍历
              for (int j = 0; j < 3; j++) {
                     printf("%d ", p[j]);
              }
              p += 3; // 每行3个元素,所以跳到下一行;
              printf("\n");
       }

猜你喜欢

转载自blog.csdn.net/qq_28837389/article/details/92804593