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++知识库 -> c/c++之指针(参考谭浩强编著的C语言第五版) -> 正文阅读

[C++知识库]c/c++之指针(参考谭浩强编著的C语言第五版)

一、指针是什么

我们知道定义一个变量,编译器会为它分配内存间,这个内存空间的地址就是指针。

注意:指针变量与指针是两个完全不同的概念,指针是地址,而指针变量是用来存储指针的变量。

总结来说指针就是变量的地址。

二、指针变量

2.1使用指针变量的例子

#include <iostream>
using namespace std;
int main()
{
	int a = 10;
	int *p;//定义指针变量p
	p = &a;//p指向变量a
	*p = 20;//通过指针修改变量a的值
	cout << a << endl;
	cout << p << endl;//结果为变量a的地址
	return 0;
}
/*注意:上述第6行的*p与第8行的*p的*的含义不一样
6行的*代表p是指针变量
8行的*是一种运算符,代表p指向的变量a
*/

2.2怎样定义指针变量

#include <iostream>
using namespace std;
int main()
{
	//定义指针变量的格式为:
	//类型名 *指针变量名
	int a = 10;
	int *p; //定义指向int的指针变量
	p = &a;//指针变量p指向a
	cout << *p << endl;
}
/*注意:
一个变量的指针的含义包括两个方面:
一是存储单元表示存储的纯地址
二指向的存储单元的数据类型
*/

2.3怎样引用指针变量

#include <iostream>
using namespace std;
int main()
{
	//怎样引用指针变量
	int a = 10;
	int *p; //定义指向int的指针变量
	p = &a;//1.给指针变量赋值
	cout << *p << endl;//2.引用指针变量指向的变量
	cout << p << endl;//3.引用指针变量的值(地址)
}
/*注意:
&是取地址运算符
*是指针运算符(间接访问运算符)
*/

2.4指针变量作为函数参数

#include <iostream>
using namespace std;
//指针变量作为函数参数
void swap(int *p1,int *p2)
{
	int temp=*p1;
	*p1 = *p2;
	*p2 = temp;

}
int main()
{
	int a = 10;
	int b = 20;
	cout << a <<"\t"<< b << endl;
	swap(&a, &b);
	cout << a <<"\t"<< b << endl;
}
/*运行结果:
10 20
20 10
*/
#include <iostream>
using namespace std;
//不能企图通过改变指针形参的值而是实参的值改变
void swap(int *p1,int *p2)
{
	int *p=p1;
	p1 = p2;
	p2 = p;

}
int main()
{
	int a = 10;
	int b = 20;
	cout << a <<"\t"<< b << endl;
	swap(&a, &b);
	cout << a <<"\t"<< b << endl;
}
/*运行结果:
10 20
10 20
函数的调用只能得到一个返回值,而使用指针变量作为函数参数,
可以得到多个变化了的值。
*/

三、通过指针引用数组

3.1数组元素的指针

#include <iostream>
using namespace std;
int main()
{

	int a[5] = { 0, 1, 2, 3, 4 };
	int *p;
	p = &a[3];//指针指向数组元素a[3]
	cout << a[3] << endl;
	cout << *p << endl;
}
/*注意:
数组名a代表的不是整个数组,而是数组元素的首地址
*/

3.2在引用数组元素时指针的运算

#include <iostream>
using namespace std;
int main()
{

	int a[5] = { 0, 1, 2, 3, 4 };
	int *p;
	p = &a[3];//指针指向数组元素
	p += 1;//指针的运算
	cout << a[3] << endl;
	cout << *p << endl;
}
/*指针p+1指向同一数组中的下一个元素
指针p-1指向同一数组中的上一个元素
注意:如果p=&a[0]或者p=a,那么*(p+i),*(a+i),a[i],p[i]
这几个是等价的。
说明:[]实际上是变址运算符,即将a[i]按照a+i计算地址,然后找出
此地址单元中的值。
注意:a是常量,a++是错误的。
*/

3.3通过指针引用数组元素

#include <iostream>
using namespace std;
int main()
{

	int a[5] = { 0, 1, 2, 3, 4 };
	int *p;
	for (int i = 0; i < 5; i++)
	{
		cout << a[i] << "\t";//下标法
	}
	cout << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << *(a + i) << "\t";//指针法
	}
	cout << endl;
	for (p = a; p < (a + 5); p++)
	{
		cout << *p << "\t";//指针法
	}
	cout << endl;
}
/*分析:
上诉第1,2方法执行效率是相同的,C编译系统将a[i]转换为*(a+i)处理的,[]是变止运算符。
即先计算地址,然后取值
第3种方法效率较高,用指针变量直接指向元素,不必每一次都计算地址
p++的操作是比较快的。像这种规律地改变地址值p++能大大提高程序执行效率
*/

3.4数组名作函数参数

#include <iostream>
using namespace std;
//数组名作为函数参数
//实际上,C编译器都是将形参数组名作为指针变量来处理的。
/*注意:
实参数组名代表一个固定的地址,或者说是指针常量,但是
形参数组名不是一个固定的地址,而是按照指针变量来处理。
*/
void Display(int a[],int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << a[i] <<"\t";
	}
	cout << endl;
}
int main()
{

	int a[5] = { 0, 1, 2, 3, 4 };
	Display(a, 5);
}

3.5通过指针引用多维数组

3.5.1多维数组元素的地址

#include <iostream>
using namespace std;

int main()
{
	int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
	cout << (int)a << "\t" << (int)(a + 1) << "\t" << (int)(a + 2) << endl;//第0,1,2行
	//a[i]与*(a+i)是等价的。
	cout << (int)a <<"\t"<< (int)a[1] << "\t"<<(int)a[2] << endl;//第0,1,2行
	cout << (int)*a << "\t" << (int)*(a + 1) << "\t" << (int)*(a + 2) << endl;//第0,1,2行
	//a[i]+j<=>*(a+i)+j<==>&a[i][j];
	//a[i][j]<=>*(*(a+i)+j);
	cout << int(a[1] + 0) << "\t" << (int)*(a + 1) + 0 << "\t" << (int)&a[1][0] << endl;
	return 0;
}
/*关于a[i]性质的进一步说明:
a[i]从形式上看是a数组元素中序号为i的元素。
如果a是一维数组名,则a[i]代表a数组序号为i的存储单元。
如果a是二维数组名,则a[i]是一维数组名,它只是一个地址,
并不代表一个存储单元,也不代表存储单元中的值。
注意:
虽然a+i与*(a+i)的值是一样的,但是它们的基类型不一样。
*/

3.5.2指向数组元素的指针变量

#include <iostream>
using namespace std;
int main()
{
	int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
	int *p;//指向数组元素的指针变量
	for (p = a[0]; p < a[0] + 6; p++)//如果写成p=a会报错
		cout << *p << "\t";
	cout << endl;
	int(*pp)[3];//指向由3个元素组成的一维数组的指针变量
	pp = a;
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			//a[i][j]<=>*(*(a+i)+j);
			cout << *(*(pp + i) + j) << "\t";
		}
		cout << endl;
	}
	return 0;
}

3.5.3指向数组的指针作为函数参数

#include <iostream>
using namespace std;
//指向数组元素的指针变量作为函数参数
void average(int *p, int n)
{
	double sum = 0;
	for (int i = 0; i < n; i++)
	{
		sum += *(p + i);
	}
	cout << sum / n << endl;
}
//指向3个元素组成的一维数组的指针变量作为函数参数
void select(int(*p)[3], int n)
{
	for (int i = 0; i < 3; i++)
	{
		//a[n][i]<=>*(*(a+n)+i);
		cout << *(*(p + n) + i) << "\t";
	}
	cout << endl;
}
int main()
{
	//注意:实参与形参如果是指针变量,应当注意他们的基类型必须一致
	int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
	average(a[0], 6);//注意,此处如果是average(a, 6),则会报错,因为基类型不一样
	select(a, 1);
	return 0;
}

四、通过指针引用字符串

4.1字符串的引用方式

#include <iostream>
using namespace std;
int main()
{
	char *p = "adhashdasj";//存放在全局区
	char ch[] = "fjffdfsdsd";//存放在栈区
	p = "aaaaa";//改变指向
	printf("%s\n", p);
	//%s是格式符,输出指针变量p指向的第一个字符后,系统会自动使string+1,
	//直到遇到'\0'为止。注意:数值数组是不能这样用的。
	cout << *p << endl;//输出的是一个字符a,而不是字符串。
	printf("%c\n", p[3]);
	printf("%s\n", ch);
	printf("%c\n", ch[3]);
	
	static int a = 0;//存放在全局区
	int b = 0;//存放在栈区
	
	cout << (int)p << endl;//存放在全局区
	cout << (int)&a << endl;//存放在全局区
	
	cout << (int)ch << endl;//存放在栈区
	cout << (int)&b << endl;//存放在栈区	
	
	//总结:字符串常量与字符数组的存储地址是不一样的。
}

4.2字符指针作为函数参数

用法同数组名作函数参数一样,这里不再介绍。

无非是类型由int变为char。

4.3字符指针变量和字符数组的比较

#include <iostream>
using namespace std;
int main()
{
	//1.字符数组由若干个元素组成,每个元素中存放一个字符,而
	//字符指针变量中存放的是一个地址。
	//2.可以对字符指针变量赋值,但是不能对数组名赋值
	//3.指针变量的值是可以改变的,而字符数组名代表一个固定的值,不能改变。
	//4.字符数组中元素的值是可以改变的,但是字符指针变量指向的字符串常量的值不能改变
	//5.字符串常量存储的地址与字符数组存储的地址不在同一个区,
	//字符串常量在全局区,而字符数组存储在栈区。
	char *p;
	p = "China";//合法
	//p = "dasdsadasd";//合法
	char ch[] = "China";
	//ch = "dssssas";//非法
	//p[2] = 'A';//虽然编译的时候不会报错,但是执行的时候运行不出结果。 
	ch[2] = 'A';
	printf("%s\n", p);
	printf("%s\n", ch);
	return 0;
}

五、指向函数的指针

5.1什么是函数的指针

函数名代表函数的起始地址。

函数名就是函数的指针,它代表函数的起始地址

5.2用函数指针变量调用函数

#include <iostream>
using namespace std;
int max(int x,int y)
{
	if (x > y)
		return x;
	else
		return y;
}
int main()
{
	int a = 10;
	int b = 20;
	int c;
	//c = max(a, b);//通过函数名调用函数
	int(*p)(int, int);//定义指向函数的指针变量p
	p = max;//p指向max函数
	c = (*p)(a, b);//通过指针变量调用函数
	cout << "max:" << c << endl;
	return 0;
}
/*注意:int(*p)(int, int)如果不能写成int *p(int, int)。
如果写成int *p(int, int),就变成了一个p函数,函数的返回值是指向整形变量的指针。
*/

5.3定义和使用指向函数的指针变量

#include <iostream>
using namespace std;
int Max(int x,int y)
{
	if (x > y)
		return x;
	else
		return y;
}
int Min(int x, int y)
{
	if (x > y)
		return y;
	else
		return x;
}
int main()
{
	//定义指向函数的指针变量的形式:
	//类型名 (*指针变量名)(函数参数列表)
	int a = 10;
	int b = 20;
	int min,max;
	int(*p)(int, int);//定义指向函数的指针变量p
	p = Max;//p指向Max函数
	max = (*p)(a, b);//通过指针变量调用函数
	p = Min;//p指向Min函数
	min = (*p)(a, b);//通过指针变量调用函数
	cout << "max:" <<max << endl;
	cout << "min:" << min<< endl;
	return 0;
}
/*注意:
指向函数的指针变量不能进行算术运算
*/

5.4指向函数的指针作为函数参数

#include <iostream>
using namespace std;
int fun(int x, int y, int(*p)(int, int))
{
	return (*p)(x, y);
}
int Max(int x,int y)
{
	if (x > y)
		return x;
	else
		return y;
}
int Min(int x, int y)
{
	if (x > y)
		return y;
	else
		return x;
}
int main()
{
	//指向函数的指针变量的一个重要用途就是把函数的入口地址作为参数传递到其他函数。
	int a = 10;
	int b = 20;
	int max,min ;
	max = fun(a, b, Max);//指向函数的指针变量作为函数参数
	min = fun(a, b, Min);//指向函数的指针变量作为函数参数
	cout << "max:" <<max << endl;
	cout << "min:" << min<< endl;
	return 0;
}

六、返回指针值的函数

#include <iostream>
using namespace std;
//p是指向由3个元素组成的一维数组的指针变量
int *search(int (*p)[3],int n)
{
	return  *(p + n);//返回第n行的地址
}
int main()
{
	//定义返回指针值的函数原型的一般形式为:
	//类型名 * 函数名(参数列表);
	int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
	int *p;
	for (int i = 0; i < 3; i++)
	{
		p = search(a, i);//返回第i行的地址
		for (int j = 0; j < 3; j++)
		{
			cout << *(p + j)<<"\t";//输出第i行j列的元素
		}
		cout << endl;
	}   
	return 0;
}

关于指针变量的类型及含义的总结:

变量定义类型表示含义
int iint定义整形变量i
int *pint *定义p为指向整型数据的指针变量
int a[5]int [5]定义整形数组a,它由5个元素
int *p[4]int *[4]定义指针数组p,它由4个指向整形数据的指针元素组成
int (*p)[4]int (*)[4]p为指向包含由四个元素组成的一维数组的指针变量
int f()int ()f为返回整形函数值的函数
int *p()int *()p为返回一个指针的函数,该指针指向整形数据
int (*p)()int (*)()p为指向函数的指针,该函数返回一个整形值
int *pint **p为一个指针变量,它指向一个指向整形数据的指针变量
void *pvoid *p是一个指针变量
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:29:00  更:2021-09-22 14:30:03 
 
开发: 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年12日历 -2024/12/28 12:35:33-

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