文章目录
指针和数组
函数数组和指针
使用指针形参
指针操作
指针和数组
数组名是数组元素的首地址
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; }
在C中,指针+1指的是增加一个储存单元
对于数组而言,表示下一个元素的地址
指针加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; }
使用指针形参
使用函数处理数组,必须要知道何时开始,何时结束。除了上面的方法传参,我们还可以传递两个指针,第一个指针指向数组的开始处,第二个指针指向数组的结束处。比如下面:
#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; }
指针操作
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); }
取值:和所有变量一样,指针变量也有自己的地址和值。对与指针来说,&运算符给出指针值的地址,
#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); }
这里用到的三个参数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程序员创建了指针数组,函数指针,指向指针的指针数组,指向函数的指针数组等