数组和指针

本文围绕C语言指针展开,介绍了指针概念、大小,二级指针、数组指针、函数指针的含义及使用,分析了野指针产生的原因,给出使用指针的注意事项,对比了指针和数组的区别,最后提供了相关练习题,帮助理解和掌握指针知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针概念

指针是C语言中的一种数据类型,用这种类型定义的数据变量称为指针变量,该变量存放的是一个地址。

 int a = 10;
 int *p = &a;//指针变量p保存的是整型变量a的地址
 printf("%p %d", p, *p);//通过解引用可以访问地址上存储的值

在这里插入图片描述
比如:你有一个箱子,里面有你想要的东西,你用钥匙打开箱子拿到东西,这个钥匙就是一个一级指针。

指针大小

32位机器下:指针为4个字节
在这里插入图片描述
在32位的平台上,指针大小永为4
在这里插入图片描述

64位机器下:VS默认按照32位方式编译,所以指针大小还是为4,但是可以对编译器设置,让其按照64位的方式进行编译,此时指针大小为8
在这里插入图片描述
对编译器设置让程序按照64位的方式进行编译:
在这里插入图片描述

二级指针

你有一个箱子,里面有你想要的东西,你用钥匙打开箱子拿到东西,这个钥匙就是一个一级指针。如果,这个钥匙不能直接打开你的箱子,但可以打开存放开你这个箱子钥匙的箱子,这个钥匙就是一个二级指针。二级指针是一个存放一级指针的地址的变量

       int a = 10;
       int *p = &a;
       int **p1 = &p1;
       printf("%d %x\n", *p, *p1);
       printf("%p %p %p\n", p, p1,&a);

结果:
在这里插入图片描述

p存放变量10的地址;
p1存放指针变量p的地址
p1通过**p1找到p,对p进行解引用找到a.”

那么二级指针多大呢?
在32位平台上,当然还是4
在这里插入图片描述
指针中存放的是变量的地址,32位平台上,地址的大小时32bit为,4byte的大小。(可以这样认为指针就是地址)

数组指针

数组指针是数组还是指针?
回:是指针
int* p;是能够指向整型变量的指针,float* p;是可以指向浮点型变量的指针。那么顾名思义,数组指针就是可以指向数组的指针。

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
答:p1是存放10int*类型数据的数组名
p2是指向存放10个元素的数组的指针变量名

数组指针的使用:

void print_arr2(int (*arr)[5], int row, int col)
{
 	int i = 0;
 	for(i=0; i<row; i++)
	 {
		 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_arr2(arr, 3, 5);
	return 0;
}

数组名arr,表示首元素的地址
但是二维数组的首元素是二维数组的第一行
所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址,可以数组指针来接收

函数指针

函数指针是一个指针,用来存储函数地址。

#include <stdio.h>
void test()
{
    printf("hehe\n");
}
int main()
{
    printf("%p\n", test);
    printf("%p\n", &test);
    return 0;
}
结果:hehe
    hehe
test和&test是等同的

利用函数指针保存函数地址。

int max(int a,int b)
{
    return a>b?a:b;
}
//把函数指针当做参数
int fun(int a,int(*p)(int,int))
{
    int ret=p(10,20);
    return ret>a:ret:a;
}
int main()
{
    fun(10,max)
    int (*p)(int ,int) = max;
    int sum = (*p)(10,20);
    //==>等同与p(10,20),也就是test(10,20)
    return 0;
}
int (*pf)(int *,char );指向返回值为int,有两个参数,分别是int*,char类型参数的函数。

野指针

野指针就是指针指向的位置是不可知的,不确定的。
野指针产生的原因:

  1. 指针未初始化
  2. 指针指向的空间被释放了,但是没有把该指针指向一个合法的位置
  3. 指针越界访问,比如在遍历数组时,访问超过数组元素个数

使用指针时的注意事项

  1. 一般情况下,定义一个指针变量,最好让该指针变量有一个合法的指向,如果没有合法的指向,则指向NULL
  2. 避免产生野指针,或者垂悬指针( 指针指向访问受限的空间或该空间以及被释放的空间 )
  3. 在使用指针时,最好先判空

指针和数组的区别

数组:一组相同元素的集合
一维数组的使用:

#include <stdio.h>
int main()
{
    int arr[10] = {0};//数组的不完全初始化
    int sz = sizeof(arr)/sizeof(arr[0]);//计算数组的元素个数
    int i = 0;//数组下标从0开始
    for(i=0; i<sz; i++)
    {
        arr[i] = i;
    }
    for(i=0;i<sz;++i)//输出数组的内容
    {
        printf("%d\n",arr[i]);
    }
    return 0;
}

在这里插入图片描述
一维数组在内存中的存储:

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

结果:
在这里插入图片描述
随着数组下标的增长,元素地址有规律的递增。数组在内存中是连续存放的。
二维数组(是一个特殊的一维数组):

定义一个二维数组arr[3][3],由于二维数组在内存中也是按照顺序存储,所以,arr[2]其实就相当是一个数组指针;指向arr[0][0],arr[2][1],arr[2][2]

指针数组
指针数组:存放指针的数组

int *arr[3];
//[]优先级高,所以arr[3]先结合,是一个数组,
//里面存放int *类型变量

eg:

int arr1[3]={1,2,3};
int arr2[3]={4,5,6};
int arr3[3]={7,8,9};
int * p[3]={arr1,arr2,arr3};
int **q=p;
//p是数组名,代表数组首元素地址
//首元素是一个int *类型的地址,需要int**去接收

在这里插入图片描述

数组的特性:

  1. int arr[10];
  2. 数组的类型,
  3. int [10] 数组存储元素的类型,
  4. int 数组名不能直接++、–
  5. 只有在sizeof(arr),&arr时,arr表示的是数组本身

指针和数组的区别:

1.数组存放的是数据,指针存放的是地址
2.数组直接对元素进行访问,指针要通过解引用才能访问,间接访问
3.指针通常用于动态数据结构,数组用于存放固定数目且类型相同的元素
4.指针通常指向匿名数据,数组存放已知的

相关练习题

有关数组和指针常见的问题练习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值