1.数组指针(指向数组的指针)
数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。
- 以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);
int i;
for(i=0; i<len; i++){
printf("%d ", *(arr+i) );
}
printf("\n");
return 0;
}
我们也可以定义一个指向数组的指针,例如: int arr[] = { 99, 15, 100, 888, 252 }; int *p = arr;
- arr (数组名)本身就是一个指针,可以直接赋值给指针变量 p。arr 是数组第 0 个元素的地址,所以int *p = arr;也可以写作int *p = &arr[0];。也就是说,arr、p、&arr[0] 这三种写法都是等价的,它们都指向数组第 0 个元素,或者说指向数组的开头。
如果一个指针指向了数组,我们就称它为数组指针(Array Pointer)。数组指针指向的是数组中的一个具体元素,而不是整个数组
#include <stdio.h>
int main(){
int arr[] = { 99, 15, 100, 888, 252 };
int i;
int* p = arr;
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;
}
*p++ 应该理解为 *(p++),每次循环都会改变 p 的值(p++ 使得 p 自身的值增加),以使 p 指向下一个数组元素。该语句不能写为 *arr++,因为 arr 是常量,而 arr++ 会改变它的值,这显然是错误的。
2.字符串指针(指向字符串的指针)
字符数组归根结底还是一个数组,关于指针和数组的规则同样也适用于字符数组。使用指针的方式来输出字符串:
#include <stdio.h>
#include <string.h>
int main(){
char str[] = "http://c.biancheng.net";
char *pstr = str;
int len = strlen(str), i;
for(i=0; i<len; i++){
printf("%c", *(pstr+i));
}
printf("\n");
for(i=0; i<len; i++){
printf("%c", pstr[i]);
}
printf("\n");
for(i=0; i<len; i++){
printf("%c", *(str+i));
}
printf("\n");
return 0;
}
除了字符数组,C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,即:字符串指针。例如 char *str = "http://c.biancheng.net"; 或者 char *str; str = "http://c.biancheng.net";
- 字符串中每个字符的类型都是char,所以 str 的类型也必须是char *。
下面的例子演示了如何输出这种字符串:
#include <stdio.h>
#include <string.h>
int main(){
char *str = "http://c.biancheng.net";
int len = strlen(str), i;
printf("%s\n", str);
for(i=0; i<len; i++){
printf("%c", *(str+i));
}
printf("\n");
for(i=0; i<len; i++){
printf("%c", str[i]);
}
printf("\n");
return 0;
}
3.指针变量作为函数参数
在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。
- 用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。
例如
#include <stdio.h>
#include <string.h>
void swap(int* pa, int* 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;
}
数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。下面的例子定义了一个函数 max(),用来查找数组中值最大的元素:
#include <stdio.h>
#include <string.h>
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);
}
printf("Max value is %d!\n", max(nums, len));
return 0;
}
int max(int* arr, int len)
{
int i, maxValue = arr[0];
for(i=1; i<len; i++)
{
if(maxValue < arr[i])
maxValue = arr[i];
}
return maxValue;
}
4.指针变量作为函数返回值
C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个:
#include <stdio.h>
#include <string.h>
char* strlong(char* str1, char* str2);
int main()
{
char str1[20], str2[30], *str;
gets(str1);
gets(str2);
str = strlong(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;
}
}
|