1.数组指针(指向数组的指针)
- 以int arr[] = { 99, 15, 100, 888, 252 };为例,该数组在内存中的分布如下图所示:
- 定义数组时,要给出数组名和数组长度,数组名可以认为是一个指针,它指向数组的第 0 个元素。在C语言中,我们将第 0 个元素的地址称为数组的首地址。以上面的数组为例,下图是 arr 的指向:
下面的例子演示了如何以指针的方式遍历数组元素:
#include <stdio.h>
int main(){
int arr[] = { 99, 15, 100, 888, 252 };//[]内的数字由后面的内容自动生成
int len = sizeof(arr) / sizeof(int); //求数组长度
//sizeof(arr) 会获得整个数组所占用的字节数,sizeof(int) 会获得一个数组元素所占用的字节数,
//它们相除的结果就是数组包含的元素个数,也即数组长度。
int i;
for(i=0; i<len; i++){
printf("%d ", *(arr+i) );
//arr为数组首元素地址;arr+i 指向数组的第 i 个元素;
//*(arr+i) 表示取第 i 个元素的数据,它等价于 arr[i]。
}
printf("\n");
return 0;
}
#include <stdio.h>
int main(){
int arr[] = { 99, 15, 100, 888, 252 };
int i;
int* p = arr;
//定义一个指向数组的指针,我们把这个指针p称为数组指针
int len = sizeof(arr) / sizeof(int);
for(i=0; i<len; i++){
printf("%d ", *(p+i) );
}
printf("\n");
return 0;
}
引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。
- 使用下标
也就是采用 arr[i] 的形式访问数组元素。如果 p 是指向数组 arr 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 arr[i]。 - 使用指针
也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(arr+i) 来访问数组元素,它等价于 *(p+i)。
不管是数组名还是数组指针,都可以使用上面的两种方式来访问数组元素。不同的是,数组名是常量,它的值不能改变,而数组指针是变量(除非特别指明它是常量),它的值可以任意改变。也就是说,数组名只能指向数组的开头,而数组指针可以先指向数组开头,再指向其他元素。
#include <stdio.h>
int main(){
int arr[] = { 99, 15, 100, 888, 252 };
int i, *p = arr, len = sizeof(arr) / sizeof(int);
for(i=0; i<len; i++){
printf("%d ", *p++ );
}
printf("\n");
return 0;
}
2.字符串指针(指向字符串的指针)
#include <stdio.h>
#include <string.h>
int main(){
char str[] = "http://c.biancheng.net";
char *pstr = str;
int len = strlen(str), i;
//使用*(pstr+i)
for(i=0; i<len; i++){
printf("%c", *(pstr+i));
}
printf("\n");
//使用pstr[i]
for(i=0; i<len; i++){
printf("%c", pstr[i]);
}
printf("\n");
//使用*(str+i)
for(i=0; i<len; i++){
printf("%c", *(str+i));
}
printf("\n");
return 0;
}
下面的例子演示了如何输出这种字符串:
#include <stdio.h>
#include <string.h>
int main(){
char *str = "http://c.biancheng.net";
int len = strlen(str), i;
//直接输出字符串
printf("%s\n", str);
//使用*(str+i)
for(i=0; i<len; i++){
printf("%c", *(str+i));
}
printf("\n");
//使用str[i]
for(i=0; i<len; i++){
printf("%c", str[i]);
}
printf("\n");
return 0;
}
3.指针变量作为函数参数
-
像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。
-
有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。
例如
#include <stdio.h>
#include <string.h>
void swap(int* pa, int* pb);
//传进来的参数是指针变量,指针变量用来存放地址
//将变量 a、b 的地址分别赋值给 pa、pb
int main()
{
int a = 1, b = 2;
swap(&a, &b);
printf("a=%d, b=%d\n", a, b);
return 0;
}
void swap(int* pa, int* pb)
{
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
#include <stdio.h>
#include <string.h>
//用数组作函数参数
//在函数内部无法通过这个指针获得数组长度,因为 intArr 仅仅是一个指针,
//而不是真正的数组,所以必须要额外增加一个参数来传递数组长度。
//这就是为什么需要两个函数参数的原因
//所以必须将数组长度作为函数参数传递到函数内部。
int max(int* arr, int len);
//需要传进来一个指针(数组名=首元素地址)
//也可以写成int max(int arr[], int len);此时[]里面写了数字也不起效,因为不会真正传进去
int main()
{
int nums[3], i;
int len = sizeof(nums)/sizeof(int);
//读取用户输入的数据并赋值给数组元素
for(i=0; i<len; i++)
{
scanf("%d", nums+i);//nums为数组名,相当于首元素地址
//也可以写成nums[0]+i;nums[0]为首元素地址
}
printf("Max value is %d!\n", max(nums, len));
//数组名传进去的是数组首元素的地址,相当于一个指针
return 0;
}
int max(int* arr, int len)
{
int i, maxValue = arr[0];//先假设第0个元素是最大的
for(i=1; i<len; i++)
{
if(maxValue < arr[i])
maxValue = arr[i];
}
return maxValue;
}

4.指针变量作为函数返回值
#include <stdio.h>
#include <string.h>
char* strlong(char* str1, char* str2);//函数声明
int main()
{
char str1[20], str2[30], *str;
gets(str1);
gets(str2);
//gets从标准输入设备读字符串函数,其可以无限读取,
//不会判断上限,以回车结束读取,
str = strlong(str1, str2);
//因为返回值是地址,所以要用指针变量str去接受
//数组名str1, str2都是代表数组首元素的地址,所以不用加&
printf("The longer string is :%s\n", str);
return 0;
}
char* strlong(char* str1, char* str2)
{
if(strlen(str1)>=strlen(str2))
{
return str1;
}else
{
return str2;
}
}