指针和数组

简介: 使用指针能使程序更高效,指针还能有效的处理数组,数组表示法其实是在变相的使用指针 好 开始学习 GO

文章目录


指针和数组


函数数组和指针


使用指针形参


指针操作


指针和数组


数组名是数组元素的首地址


int a[3];
a==&a[0]; //数组名表示数组元素的首地址


#include<stdio.h>
#define SIZE 5
int main()
{
    int dates[SIZE];
    int *pt1;
    long a[SIZE];
    long *pt2;
    printf("        %s                 %s\n","int","long");
    for(int i=0;i<SIZE;i++)
        printf(" +  %d:  %10p  %10p\n",i,pt1+i,pt2+i);
    return 0;
}

20210714212230826.png


在C中,指针+1指的是增加一个储存单元

对于数组而言,表示下一个元素的地址


20210714213700854.png


指针加1,指针的值递增它所指向类型的大小(以字节为单位)

假设a是整型数组,下面这样是✔


a+1==&a[1];  //相同的地址
*(a+2)==a[2]; //相同的值


可以看到数组和指针就好像是好基友,咳咳,可以使用指针表示数组的元素和获取数组元素的值


注意:间接运算符 * 的优先级高于算术运算符+


*(a+2);  //a的第三个元素的值
*a+2;  //a的第一个元素的值加2


学到这,我们在写代码时可以选择数组表示和指针表示,我们可以用指针表示数组,反过来,也可以用数组表示指针,在使用以数组为参数的函数时应注意


函数数组和指针


假设有需求,需要一个处理数组的函数,该函数返回数组中的所有元素之和


思路:

通过循环一次读入数组数据迭代计算求和,需要掌握宏定义,自定义函数,以及数组和循环结构


函数原型:


//函数原型
int sum(int arr[],int n);


函数定义:


//函数定义
int sum(int arr[],int n)
{
    int total = 0;
    for(int i=0;i<10;i++)
    total+=arr[i];
    return total;
}


函数调用:


//函数调用
    int answer = sum(sd,SIZE);


完整代码:


#include<stdio.h>
#define SIZE 10
int sum(int arr[],int n);
int main(void){
    int sd[SIZE] = {10,20,30,40,50,60,70,80,90,100};
    int answer = sum(sd,SIZE);
    printf("%d\n" ,answer);
    printf("%zd",sizeof sd);
    return 0;
}
int sum(int arr[],int n)
{
    int total = 0;
    for(int i=0;i<10;i++)
    total+=arr[i];
    return total;
}

43.png


使用指针形参


使用函数处理数组,必须要知道何时开始,何时结束。除了上面的方法传参,我们还可以传递两个指针,第一个指针指向数组的开始处,第二个指针指向数组的结束处。比如下面:


#include<stdio.h>
#define SIZE 10
int sum(int *start,int *end);
int main()
{
    int a[SIZE]={10,20,30,40,50,60,70,80,90,100};
    int b=sum(a,a+SIZE);
    printf("%d\n",b);
    return 0;
}
int sum(int *start,int *end){
   int a=0;
   while(start<end){
       a+=*start;
       start++;
   } 
   return a;
}

44.png


指针操作


C可以对指针进行什么操作呢,我们来学习一些基本的指针操作


1.赋值:可以把地址赋给指针。例如:使用数组名,地址运算符&的变量名,另一个指针等进行赋值。


地址应该与指针的类型兼容,就是说int型的地址给int型的指针,C99/C11已经强制不允许类型不兼容


int a[3]={1,2,3};
int *ptr,*ptr1;
ptr=a;
ptr1=&a[1];


这就是把整型数组a的首地址赋值给整型指针ptr,把整型数组a的第二个地址赋值给整型指针ptr1


2.解引用和取值:*运算符给出指针指向地址上储存的值


解引用:


#include<stdio.h>
int main(){
    int a[3]={1,2,3};
    int *ptr,*ptr1;
    ptr=a;
    ptr1=&a[1];
    printf("%d\n",*ptr);
}

49.png


取值:和所有变量一样,指针变量也有自己的地址和值。对与指针来说,&运算符给出指针值的地址,


#include<stdio.h>
int main(){
    int a[3]={1,2,3};
    int *ptr,*ptr1;
    ptr=a;
    ptr1=&a[1];
    printf("ptr1=%p,*ptr1=%d,&ptr1=%p\n",ptr1,*ptr1,&ptr1);
}

39.png


这里用到的三个参数ptr1指的是指针所在的地址,*ptr1解引用指针所指向的值,&ptr1指针所指向的值的地址


3.递增递减指针:数组元素的指针可以让指针移动至数组的下一个元素。递减当然就是再回去了


int a[]={1,2,3};
int ptr1;
ptr1=&a[1];
ptr1++;//让指针移动至数组的下一个元素a[2],即递增四个字节
ptr--;//让指针移动至数组的上一个元素a[1],即递减四个字节


4.指针求差:可以计算两个指针的差值,可以用一个指针减去另一个指针得到一个整数,或者用一个指针减去一个整数得到另一个指针


注意:千万不要解引用未初始化的指针


int *pt1;//未初始化的指针
*pt=5;//严重错误


这把5储存在了pt指向的位置,但是pt未初始化,其值是一个随机值,幸运点没什么问题,或者会擦写数据或代码,甚至导致系统的崩溃。


切记:创建一个指针时,系统只分配了储存本身的内存,并未分配储存数据的内存,因此,在使用指针之前,必须先用已分配的地址初始化它


int a[3];
int *pt1,*pt2;


基于这些操作,C程序员创建了指针数组,函数指针,指向指针的指针数组,指向函数的指针数组等



相关文章
|
12天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
28 3
|
11天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
24 2
|
20天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
24 1
|
29天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
29天前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
29天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
17 0
|
1月前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
|
3月前
|
搜索推荐 C语言
指针与数组
指针与数组
58 9