深入了解指针,指针数组,数组指针。

简介: 深入了解指针,指针数组,数组指针。

前言:

大家可能听说过这样一句话,没学过指针就是没学过C语言。指针确实时C语言的一大特色,更是C语言的一大核心。但是指针的学习也没有大家想象的这么难。今天就带大家一起来深入学习一下指针。


一.指针

指针有很多类型:

    //整形指针 
  int* a;
  //字符指针
  char* b;
  //浮点型指针
  double* c;
  //自定义结构体指针
  struct S
  {
    int a;
    char b;
  }*ss;

指针的类型代表了,指针指向的空间存储的数据类型,同时也意味着,指针在解引用时的访问能力。(例如:字符指针解引用一次就只可以解引用访问一个字节)


今天特别说以一下字符指针:

const char* ch = "hahaha";

大家看一下这段代码,大家想一下 ch 里面存储的是什么?是存储的字符串"hahaha"? 还是字符串的第一个字符的地址?


22f5257d7e404524a26e00b42c0c859a.png


const char* ch = "hahaha";

这段代码让很多小伙伴误以为是,把字符串放进 ch 里面,其实是把常量字符串的第一个字符放进  ch 里面。


看一个题目:

int main()
{
  char str1[] = "hello bit.";
  char str2[] = "hello bit.";
  const char* str3 = "hello bit.";
  const char* str4 = "hello bit.";
  if (str1 == str2)
  {
    printf("str1 and str2 are same\n");
  }
  else
  {
    printf("str1 and str2 are not same\n");
  }
  if (str3 == str4)
  {
    printf("str3 and str4 are same\n");
  }
  else
  {
    printf("str3 and str4 are not same\n");
  }
  return 0;
}

大家可以想一下执行结果。


f1629f5ff0794a4eb2e88b426d51f0a5.png


这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。


二.指针数组

(1)指针数组的定义:

大家可以猜一下,这指针数组,到底是指针还是数组?


答案是:数组。

    //整形数据,可以存储多个整形数据
  int arr[10];
  //字符数组,可以存储字符或者字符串
  char ch[10];
  //指针数组,是不是可以存储多个指针?

没错,指针数组就是用于存储指针的数组。


(2)指针数组的语法形式:

int* arr[10];


fa81e4cef7804e6384b3965a5453a9ea.png


(3)数组指针举例:

我们前面说到,字符指针可以存储一个常量字符串的首字符地址,那我们就可以用一个指针数组来存起来。

int main()
{
  char* str1 = "I'm ikun";
  char* str2 = "You are ikun";
  char* str3 = "sing jump rap basketball";
    //数组指针:
  char* kun[3] = { str1,str2,str3 };
  int sz = sizeof(kun) / sizeof(kun[0]);
  int i = 0;
  for (i = 0; i < 3; i++)
  {
    printf("%s\n", kun[i]);
  }
  return 0;
}


运行结果:


1224617d0397437d81c5dd8e404b3f08.png


三.数组指针

刚刚讲了指针数组,现在再来聊一下数组指针,这次数组指针就是一个指针了。


(1)数组指针的定义:

整形指针: int * pint; 能够指向整形数据的指针。

浮点型指针: float * pf; 能够指向浮点型数据的指针。

那数组指针应该是:能够指向数组的指针。


(2)数组指针的语法形式:

int(*p)[10];

说明:


205443f6509148dfa89b01a65c60e835.png


所以p是一个指针,指向一个数组,叫数组指针。这里要注意:[  ] 的优先级要高于*号的,所以必须加上( )来保证p先和*结合。


(3)&数组名VS数组名

对于下面的数组:

int arr[10];

arr 和 &arr 分别是啥?我们知道arr是数组名,数组名表示数组首元素的地址。那&arr数组名到底是啥?


我们看一段代码:

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%p\n", arr);
    printf("%p\n", &arr);
    return 0;
}

(%p 打印地址)


运行结果:


8f82d4113563426799338ba7c8e74d40.png


有的小伙伴看到这里是不是就以为,这不是一样的嘛。别急我们接着看一段代码。

#include <stdio.h>
int main()
{
  int arr[10] = { 0 };
  printf("arr = %p\n", arr);
  printf("arr+1 = %p\n", arr + 1);
  printf("\n");
  printf("&arr= %p\n", &arr);
  printf("&arr+1= %p\n", &arr + 1);
  return 0;
}

运行结果:


455229a057784fd18ba7e3aacffcd7ee.png


我们可以就看到,arr + 1 以后跳过了4个字节,&arr +1 以后跳过了40个字节,40是个字节归刚好是,arr数组十个元素的总大小,又因为数组在内存中是连续存放的。所以&arr + 1 就跳过了整个数组。所以这里&arr 代表的就是整个数组的地址。如果需要一个指针来存储这个数组地址,那就会用到我们的数组指针。

    int arr[10] = { 0 };
  int(*arrp)[10] = &arr;

(4)数组指针的使用:

二维数组数组名:一维数组的数组名是首元素的地址,二维数组的数组名也是首元素的地址,这里二维数组的首元素是第一个一位数组,因为二维数组也可以看作是由数个一维数组组成的,二维数组的数组名就代表了第一个一维数组的地址。


所以我们在函数传参数的时候,不仅可以以数组的形式去接收,还可以以指针的形式去接收:

#include <stdio.h>
//数组的形式接收
void print_arr1(int arr[3][5], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      printf("%d ", arr[i][j]);
    }
    printf("\n");
  }
}
//指针的形式接收
void print_arr2(int(*arr)[5], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      printf("%d ", arr[i][j]);
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
  print_arr1(arr, 3, 5);
  //数组名arr,表示首元素的地址
  //但是二维数组的首元素是二维数组的第一行
  //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
  //可以数组指针来接收
    printf("\n");
  print_arr2(arr, 3, 5);
  return 0;
}

运行结果当然也是一样的:


c2ce6828debc4490bd02d333a85b8c3d.png


最后:

今天的关于指针的讲解先讲到这。欲知后事如何,请看下期。


生命不息,奋斗不止!只要相信,只要坚持,只要你真的是用生命在热爱,那一定是天赋使命使然,那就是一个人该坚持和努力的东西,无论梦想是什么,无论路有多曲折多遥远,只要是灵魂深处的热爱,就会一直坚持到走上属于自己的舞台!真正成功的人生,不在于成就的大小,而在于你是否努力地去实现自我,喊出自己的声音,走出属于自己的道路。加油,诸君,山顶见!


相关文章
|
3天前
|
算法 Java
双指针在数组遍历中的应用
文章深入探讨了双指针技术在数组遍历中的应用,通过实战例子详细解释了快慢指针和首尾指针的不同用法,并提供了解决LeetCode相关问题的Java代码实现。
|
26天前
|
运维
开发与运维数组问题之指针的加减法意义如何解决
开发与运维数组问题之指针的加减法意义如何解决
31 7
|
26天前
|
C++ 索引 运维
开发与运维数组问题之在C++中数组名和指针是等价如何解决
开发与运维数组问题之在C++中数组名和指针是等价如何解决
18 6
|
26天前
|
存储 C++ 运维
开发与运维数组问题之指针的定义语法如何解决
开发与运维数组问题之指针的定义语法如何解决
23 6
|
2月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
2月前
|
C语言
【C语言】:详解函数指针变量,函数指针数组及转移表
【C语言】:详解函数指针变量,函数指针数组及转移表
30 2
|
2月前
|
C语言
【C语言】:详解指针数组,数组指针及(二维)数组传参(2)
【C语言】:详解指针数组,数组指针及(二维)数组传参(2)
22 1
|
2月前
|
Serverless C语言
【C语言】:对(一维)数组与指针的深入理解(1)
【C语言】:对(一维)数组与指针的深入理解(1)
23 1
|
2月前
|
存储 算法 安全
C++一分钟之-数组与指针基础
【6月更文挑战第19天】在C++中,数组和指针是核心概念,数组是连续内存存储相同类型的数据,而指针是存储内存地址的变量。数组名等同于指向其首元素的常量指针。常见问题包括数组越界、尝试改变固定大小数组、不正确的指针算术以及忘记释放动态内存。使用动态分配和智能指针可避免这些问题。示例代码展示了安全访问和管理内存的方法,强调了实践的重要性。
36 3
|
2月前
|
存储 C语言
C语言中的多级指针、指针数组与数组指针
C语言中的多级指针、指针数组与数组指针
22 0