指针

指针数组:

#include <stdio.h>

int main()
{

	int i;
	
	//这里插入一个指针,如果没有指针必须要依靠二维数组,而且会导致输出的时候比较麻烦。
	//指针指向这五个数组。 数组中每一个元素都是指针。
	 
	char *p1[5] = {
		"We are the world!",
		"Nothin'on you!",
		"Look at me now!",
		"我是中国人!",
		"ÎÒÊÇÖйúÈË£¡",
	};
	
	for(i = 0; i < 5; i++)
	{
		printf("%s\n", p1[i]);
	}
	
	return 0;
}

数组指针:

#include <stdio.h>

int main()
{

	/*
	int (*p2)[5] = {1, 2, 3, 4, 5};
	int i;

	for (i = 0; i < 5; i++);
	{
		printf("%d\n", *(p2 + i));
	}
	*/

	/*
	int temp[5] = {1, 2, 3, 4, 5};
	int (*p2)[5] = temp;
        //这里的temp表示的是temp数组的第一个元素的地址
        //(因为二者本来就是一样的,但是仅仅是值一样)
	int i;

	for (i = 0; i < 5; i++);
	{
		printf("%d\n", *(p2 + i));
	}
	*/

	int temp[5] = {1, 2, 3, 4, 5};
	int(*p2)[5] = &temp; //注意这里temp用了&
	int i;

	for (i = 0; i < 5; i++);
	{
		printf("%d\n", *(*p2 + i));
	}
        
        /*
        因为有&,所以
        1、p2为数组的地址的地址;
        2、*p2为数组的地址;
        3、*p2 + n为数组的第(n + 1)个元素的地址
        4、*(*p2)为数组第一个元素的值,*(*p2 + n)为数组的第n个元素的值
        */

	return 0;
}

二维数组与数组指针

#include <stdio.h>

int main()
{
	int array[3][4] = {
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12}
	};

	/*
	int **p = array;
	这里不能用,因为C语言不够智能,无法识别array数组的一个元素到底代表了多少字节。
	*/

	int(*p)[4] = array;

	/*
	int (*p)[3][4] = &array;
	可以这样写,但是后面的p要进行再一次的解引用,变为*(*(*p + i) + j))
	*/

	int i, j;

	//这里用到了数组指针,由于(*p)[4]代表了一维数组(4个字节),而4表示了一共有4列,所以每加上一个i就是跳转到了下一行。

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
			printf("%2d", *(*(p + i) + j));
		printf("\n");
	}

	return 0;
}

指针用于交换

/*
说起指针,相信很多人都不太了解,但是又想要去了解,却没有付诸实际行动。今天我就带领大家一起探秘指针的奥秘。花了一下午时间,晚上自习估计也在做这个。(还是不会,所以改了标题)
说起指针,很多人肯定会想到8上面的那个按键* ,为什么再加上一个字母就有了取地址等意思了呢?(注意:* 和输入的是连在一起的,例如int* float* 这都是合法的语法标识符,但是写法可能又变化比如int* p等等)
顾名思义,地址就是一个单位在内存条里面的存储位置。这个位置是一直存在的,不论是有没有单位去占用它的位置。(故输出时加上地址就会准确的输出地址,而这个地址我们看不懂,是一直比C还低级的语言)
交换是能体现指针的作用的最佳说明,如下:
*/

#include <stdio.h>

void swap_no(int a, int b);
void swap_yes(int* a, int* b);

int main()
{

	int a = 5, b = 3;

	printf("In main,互换前:a = %d, b = %d\n", a, b);

	swap_no(a, b);

	printf("In main,用指针互换前:a = %d, b = %d\n", a, b);

	swap_yes(&a, &b); //因为此处用到了指针,所以要求a和b都应该进行取地址才能输入到指针里面 

	printf("加指针后,In main,互换后:a = %d, b = %d\n", a, b);

	return 0;
}

void swap_no(int a, int b)
{

	int temp;

	printf("In swap_no,互换前:a = %d, b = %d\n", a, b);

	temp = a;
	a = b;
	b = temp;

	printf("In swap_no,互换后:a = %d, b = %d\n", a, b);
}

void swap_yes(int* a, int* b)
{

	int temp;

	printf("加指针后,In swap_yes,互换前:a = %d, b = %d\n", *a, *b);

	temp = *a;
	*a = *b;
	*b = temp;

	printf("加指针后,In swap_yes,互换前:a = %d, b = %d\n", *a, *b);
}

//如果不用指针那就只能达到交换函数里面的a, b 值的作用,而我们要求的是交换外层函数里面的a, b 值,所以只能通过交换地址来简洁的达到交换作用。
/*
结果如下:
In main,互换前:a = 5, b = 3
In swap_no,互换前:a = 5, b = 3
In swap_no,互换后:a = 3, b = 5
In main,用指针互换前:a = 5, b = 3
加指针后,In swap_yes,互换前:a = 5, b = 3
加指针后,In swap_yes,互换前:a = 3, b = 5
加指针后,In main,互换后:a = 3, b = 5
*/

引用类型

  • C语言中不能用

  • 引用(&)是标识符的别名

  • 定义一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象

  • 例如:

int i, j;
int &ri = i; // 定义int引用ri,并初始化为变量i的引用。

j = 10;
ri = j; // 相当于i = j
  • 一旦一个引用被初始化后,就不能改为指向其他对象
  • 引用可以作为形参
#include <iostream>
using namespace std;

void swap(int &a, int &b);
// 引用a了,相当于a和x是一样的,这就是双向传递效果。
// 即直接对实参进行改变,而不是形参
void swap(int &a, int &b)
{
	int t = a;
	a = b;
	b = t;
}

int main(void)
{
	int x = 5, y = 10;
	
	swap(x, y);

	cout << x << '\t' << y << endl;

	return 0;
}

函数指针

//函数指针,和数组指针一样,指向函数的指针(下面的*fp)

//typedef int (*PTR_TO_FUN)(int, int);
//int calc(PTR_TO_FUN, int, int)

int add(int, int);
int sub(int, int);
int calc(int (*)(int, int), int, int);
int (*select(char))(int, int);

int add(int num1, int num2)
{
	return num1 + num2;
}
int sub(int num1, int num2)
{
	return num1 - num2;
}
int calc(int (*fp)(int, int), int num1, int num2)
{
	return (*fp)(num1, num2);
}

//这里用的话见注释。
int (*select(char op))(int, int)
{
	switch (op)
	{
	case '+':return add;
	case '-':return sub;
	}
}

#include <stdio.h>

int main()
{
	printf("3 + 5 = %d\n", calc(add, 3, 5)); // 这里可以用(& add),更加清晰。
	printf("3 - 5 = %d\n", calc(sub, 3, 5));
	
	
	/*
	这里可以这样写
	int num1, num2;
	char op;
	int (*fp)(int, int);

	printf("请输入一个式子(如3 + 5):");
	scanf("%d%c%d", &num1, &op, &num2);

	fp = select(op);
	printf("%d %c %d = %d\n", num1, op, num2, calc(fp, num1, num2));
	*/
	
	return 0;
}

指针函数

说白了就是个函数
注意一点就是
不要返回局部变量的指针
补充一点,要是C语言中需要用到字符串,可以用指针来代表字符串的首字符的地址,然后即可找到完整的字符串。

某一次讲课的笔记

#include <stdio.h>

int main()
{

	//今天要介绍指针
	//一.指针的基本概念和用法
	// 1.一级指针的基本概念和用法
	// 2.二级指针的基本概念和用法
	// 3.多级指针
	//二.指针和数组的关系
	// 1.指针和一维数组的关系
	// 2.指针和二维数组的关系
	// 3.数组指针和指针数组的关系
	//三、指针和字符串的关系
	//四、指针和函数的关系
	//	函数指针
	int a = 10, b = 20;
	/*
	a和b分别储存在哪里?
	内存 -> 栈中(局部变量) -> &a, &b
	&:取地址运算符,能够求出一个变量的存储地址
	%d:十进制的方式打印地址
	%p/%x:十六进制方式打印地址
	*/

	printf("a,b的地址分别为:%d, %d", &a, &b);
	/*
	打印这个地址和指针有什么关系
	指针就是地址,不能赋值,不能改变
	&a = 3214324(错误的,不能改变)
	
	常量:在运算过程中,值不能改变的量(每一次运行,操作系统都会重新分配,比如地址每次都在改变)
	变量:在运算过程中,值可以发生改变的量

	&a,&b:指针常量 

	指针变量:
	怎么定义一个指针变量
	基本数据类型:
	char, short, int, long, float, double 

	int* p;靠近int说明p是属于int*型,p是属于变量,*不属于变量名的一部分
	*/
	//int* p1, p2, p3, p4, p5; 全部定义的都是指针变量吗? 只有p1是指针变量,其余都是int型

	//int* p1, * p2, * p3, * p4, * p5; 这个才是全部都是指针变量。
	
	/*
	指针变量和普通变量有什么区别
	普通变量存数值,指针变量存地址

	指针变量一定要进行初始化,只有初始化之后的指针变量才能使用。
	如果没有明确的指向,请用NULL(空指针)赋值
	已经有了明确的指向,那可以直接使用地址赋值。
	*/

	//int* pa = NULL; pa不知道指向哪里,可以看作是指向内存地址为0的地方

	int* pa = &a;

	printf("pa = %d\n", pa); //打印的是a的内存地址,*&a <=> a

	/*
	修改内存
	*:解引用运算符,间接访问运算符
	后面跟一个地址,能够直接通过地址获取这块内存
	*/

	//C语言修改常量,语法灵活(C++就不能)
	const int c = 300; //C是一个常量
	int* pc = &c; //在前面再加上一个const才能在C++上进行修改
	*pc = 800;
	printf("c = %d\n", c);

	int m = 1, n = 2;
	printf("sizeof(m = n) = %d, m = %d, m = %d\n", sizeof(m = n), m, n);
	printf("m = %d, n = %d", m, n); //m, n分别是多少?为什么没有变?

	//为什么是这样?
	//sizeof不是函数、sizeof是运算符
	//sizeof只会确定里面类型的大小,不会进行赋值运算。

	return 0;
}

结果:
a,b的地址分别为:8059772, 8059760pa = 8059772
c = 800
sizeof(m = n) = 4, m = 1, m = 2
m = 1, n = 2

void指针

#include <stdio.h>

int main()
{
	int num = 1024;
	int* pi = &num;
	char* ps = "fishc";
	void* pv;

	pv = pi;
	printf("pi:%p, pv:%p\n", pi, pv);
	//这里必须强制转化,因为在void指针下解引用是没有作用的
	printf("*pv:%d\n", *(int *)pv);

	//这里不能使用,因为pv是1024的指针,但是以字符类型输出就不对了。
	//ps = (char *)pv;

	pv = ps;
	printf("ps:%p, pv:%p\n", ps, pv);
	printf("*pv:%s\n", (char*)pv);

	return 0;
}

NULL指针

#define NULL ((void *)0)

#include <stdio.h>

int main()
{
	int* pi;
	int* p2 = NULL;

	printf("%d\n", pi);
	printf("%d\n", p2);
	/*
	这里会报错
	当你不清楚将指针初始化为什么地址时,请先请先将它初始化为NULL
	在对指针进行解引用时,先检查该指针是否为NULL
	优点:节约调试时间。
	*/

	return 0;
}

以下是C++

指向常量的指针
const指针
不能通过指向常量的指针改变所指对象的指,但指针本身可以改变,可以指向另外的对象。

int a;
const int *p1 = &a; // p1是指向常量的指针
int b;
p1 = &b; // 正确,p1本身的值可以改变
*p1 = 1; // 编译时出错,不能通过p1改变所指的对象

指针类型的常量
声明指针常量,则指针本身不能改变

int a;
int *const p2 = &a;
p2 = &b; // 错误,p2是指针常量,值不能改变

this指针

  • 隐含于类的每一个非静态成员函数中。
  • 指出成员函数所操作的对象。
    –当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。
  • 例如Point类的getX函数中:
    return x; 相当于 return this->x;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值