IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C语言-对指针的理解(2) -> 正文阅读

[数据结构与算法]C语言-对指针的理解(2)

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);  //求数组长度
    //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;
}

在这里插入图片描述

我们也可以定义一个指向数组的指针,例如:
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;
	//定义一个指向数组的指针,我们把这个指针p称为数组指针 
	int len = sizeof(arr) / sizeof(int);
    for(i=0; i<len; i++){
        printf("%d  ", *(p+i) );
    }
    printf("\n");
    return 0;
}

在这里插入图片描述
引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。

  1. 使用下标
    也就是采用 arr[i] 的形式访问数组元素。如果 p 是指向数组 arr 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 arr[i]。
  2. 使用指针
    也就是使用 *(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;

    //使用*(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;
}

除了字符数组,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);
    //使用*(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.指针变量作为函数参数

在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针

  • 用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。
  • 像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。

  • 有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。

例如

#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;
 } 

在这里插入图片描述

数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。下面的例子定义了一个函数 max(),用来查找数组中值最大的元素:

#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.指针变量作为函数返回值

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);
	//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;
	}
}
 

在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 18:07:50  更:2022-04-18 18:10:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:42:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码