p = a;
p = &a[0];
它们都是把3000这个地址值赋给了指针p。同样如下语句也是等价的:
p = a + 1 == p + 1;
p = &a[1];
它们都是把3002赋给p。数组a和指针p之间的关系如下:
【注】p = a + 1和p = p + 1语句是正确的,但a = a+1语句是错误的。
如果已经对数组a的元素进行了赋值,求数组所有元素的和。代码如下:
int sum = 0;
for(p = a; p <= &a[99]; p++)
sum += *p;
在循环中,指针变量p的初值是数组a的基地址,p连续取值&a[0], &a[1], … , &a[99]。
一般而言,如果i是int型变量,那么p + i 就是距地址p的第i个偏移,类似地,a + i 是距数组a的基地址的第i个偏移,*(a + i)与a[i]等价。下面是对数组元素求和的第二种方法:
int sum = 0;
for(i = 0; i < 100; i++)
sum += *(a + i);
正如表达式 *(a+i)与a[i]等价一样,表达式 *(p + i)与p[i]等价。下面是对数组求和的第三种方法:
p = a;
int sum = 0;
for(i = 0; i < 100; i++)
sum += p[i];
由此可知,数组名可以使用指针形式,而指针变量也可以转换为数组形式。
指针数组
上面简单讲述了指针、数组和地址间的关系,也看到了指针指向数组的简单使用,下面来看一下数组指针的使用。
C语言中的数组可以是任何类型,如果数组的各个元素都是指针类型,用于存放内存地址,那么这个数组就是指针数组。
一维指针数组定义的格式为:类型名 *数组名[数组长度];
类型名指定数组元素所指向的变量的类型。例如:
int a[10];
char *color[5];
上述代码定义了整型数组a和字符指针数组color。整型数组a有10个元素,可以存放10个整型数据;指针数组color有5个元素,元素的类型是字符指针,用于存放字符数据单元的地址。一个数组的元素均为指针型的数据。
指针数组初始化与应用
指针数组初始化与使用和数组差不多,不同的就是数组元素均为指针类型的数据。如下对指针数组的初始化:
char *color[5] = {“aaa”, “bbb”, “ccc”, “ddd”, “fff”};
color[0] = “abc”;
指针数组初始化和数组一样,上述代码定义了一个字符型指针数组。字符指针可以指向字符串,因此字符型指针数组也可以存储字符串数据。
改变指针数组中的数据,和数组一样,根据数组的下标改变。
指针数组的简单使用
#include<stdio.h>
int main(){
//初始化指针数组
char *color[5] = {“aaa”, “bbb”, “ccc”, “ddd”, “fff”};
//输出指针数组中内容
for(int i = 0 ; i < 5; i ++){
printf("%s\t", color[i]);
}
//改变指针数组中的第一个元素
color[0] = “abc”;
printf("\n");
for(int i = 0 ; i < 5; i ++){
printf("%s\t", color[i]);
}
//把指针数组中第一个元素与最后一个元素交换位置
char *str= color[0];
color[0] = color[4];
color[4] = s
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
tr;
printf("\n");
for(int i = 0 ; i < 5; i ++){
printf("%s\t", color[i]);
}
return 0;
}
上述代码先定义了一个字符型指针数组并初始化,改变了指针数组的第一个值和交换指针数组中第一个和最后一个元素的位置操作。
运行效果如下:
通过上述案例可以看出使用字符型指针数组可以操作多个字符串。如果不用指针数组,操作多个字符串就只能使用二维数组来实现,因为每个字符串的长度可能不一样,所以使用二维数组来操作多个字符串,会造成内存单元的浪费。推荐使用指针数组去操作多个字符串。
指向指针的指针
定义指针是 类型名 *变量名; 定义的。定义指向指针的指针格式如下:
类型名 * *变量名;
指向指针的指针也称为二级指针。与一级指针相比,二级指针要相对复杂一些。
定义二级指针并初始化
int a = 10;
int *p = &a;
int **pp = &p;
上述代码定义了3个变量a、p和pp并初始化。一级指针p指向整形变量a,二级指针pp指向一级指针p。如下如:
由于p指向a,所以p和&a的值一样,a和 *p代表同一个单元;由于pp指向p,所以pp和&p的值一样,p和 *pp代表同一个单元。由此可知&&a、&p和pp等价,&a、p和 *pp等价,a、*p和 **pp代表同一个单元,它们的值都相同。
二级指针的简单使用
#include<stdio.h>
int main(){
//定义及初始化
int a = 10, b = 20;
int *x = &a, *y = &b;
int **p = &x;
printf(“a = %d, *x = %d, *y = %d, **p = %d\n”, a, *x, *y, **p);
//改变一级指针x和y指向地址的数据值
*x = 100;
*y = 200;
printf(“a = %d, *x = %d, *y = %d, **p = %d\n”, a, *x, *y, **p);
//改变二级指针指向的地址
p = &y;
printf(“a = %d, *x = %d, *y = %d, **p = %d\n”, a, *x, *y, **p);
//改变二级指针指向地址的数据值
**p = 400;
printf(“a = %d, *x = %d, *y = %d, **p = %d\n”, a, *x, *y, **p);
return 0;
}
定义并初始化指针,对指针地址及地址数据值进行修改操作,运行效果如下:
指向函数的指针
在C语言中,函数名代表函数的入口地址。可以定义一个指针变量,接收函数的入口地址,让它指向函数,这就是指向函数的指针,也称为函数指针。通过函数指针可以调用函数,它还可以作为函数的参数。
函数指针的定义
函数指针定义的一般格式为:
类型名 (*变量名) (参数类型表)
类型名指定函数返回值的类型,变量名是指向函数的指针变量名称。例如:
int (*funptr) (int, int);
定义了一个函数指针funptr,它可以指向有两个整型参数且返回值类型为int的函数。
通过函数指针调用函数
在使用函数指针前,需要先对它赋值。赋值时,将一个函数名赋给函数指针,但该函数必须已定义或声明,且函数返回值的类型和函数指针的类型要一致。
假设函数fun(x, y)已定义,它有两个整型参数且返回一个整型数据,则: