复习总结一下: 指针的内容

为什么要使用指针

 函数的值传递,无法通过调用函数,来修改函数的实参
 被调用函数需要提供更多的“返回值”给调用函数
 减少值传递时带来的额外开销,提高代码执行效率

指针的初始化、访问

指针的初始化
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

int main() {
	int room = 2;

	int *p1 = &room;
	int *p2 = &room;

	printf("room address: 0x%p\n", &room);

	printf("p1 address: 0x%p\n", &p1);
	printf("p2 address: 0x%p\n", &p2);
	
	printf("room Number of bytes: %d\n", sizeof(room));
	printf("p1 Number of bytes: %d\n", sizeof(p1));
	printf("p2 Number of bytes: %d\n", sizeof(p2));

	return 0;
}

在这里插入图片描述
注意:
32 位系统中,int 整数占 4 个字节,指针同样占 4 个字节
64 位系统中,int 整数占 4 个字节,指针同样占 8 个字节

指针的访问

访问指针

#include <stdio.h>
#include <stdlib.h>

int main() {
	int room = 2;
	int room1 = 3;

	int *p1 = &room;
	int *p2 = p1;

	int *p3 = p1;
	printf("room address: %d\n", &room);
	printf("p1 value: %d p2 value: %d\n", p1, p2);
	printf("p3 value: %d\n", p3);

	p3 = &room1;
	// not recommend
	printf("p3 value: %d, room1 address: %d\n", p3, &room1); 

	// recommend
	printf("p1=0x%p\n", p1);
	printf("p1=0x%x\n", p1);
	printf("p1=0x%X\n", p1);

  	return 0;
}

运行结果:
在这里插入图片描述
访问指针所指向的内容
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

int main() {
	int room = 2;

	int * girl = &room;

	int x = 0;
	x = *girl;
	printf("x: %d\n", x);

	*girl = 4;
	printf("room: %d, *girl: %d\n", room, *girl);

	return 0;	
}

运行结果:
在这里插入图片描述

空指针和坏指针

#include <stdio.h>
#include <stdlib.h>

int main() {
	int room1 = 666;
	int room2 = 888;

	int girl;

	int *select;

	scanf("%d", &girl);

	if (girl == 666){
		select = &room1;
	}else if (girl == 888) {
		select = &room2;
	}

	printf("The chosen room is: %d\n", *select);
	
	return 0;
}

运行结果:
在这里插入图片描述
1. 什么是空指针?
2. 空指针,就是值为 0 的指针。(任何程序数据都不会存储在地址为 0 的内存块中,它是被操作系 统预留的内存块。)
int *p = 0;
或者
int *p = NULL; //强烈推荐
2. 空指针的使用
1)指针初始化为空指针
int *select = NULL;
目的就是,避免访问非法数据。
2)指针不再使用时,可以设置为空指针
int *select = &xiao_long_lv;
//和小龙女约会
select = NULL;
3)表示这个指针还没有具体的指向,使用前进行合法性判断
int *p = NULL;
// 。。。。
if § { //p 等同于 p!=NULL
//指针不为空,对指针进行操作
}
3. 坏指针
int *select; //没有初始化
情形一
printf(“选择的房间是: %d\n”, *select);
情形二
select = 100;
printf(“选择的房间是: %d\n”, *select);

渣男、直男、暖男的区别:const

#include <stdio.h>
#include <stdlib.h>

// const pointer
int main() {
	int wife = 24;
	int girl = 18;

	// The first kind of
	int * zha_nan = &wife;
	*zha_nan = 25;
	zha_nan = &girl;
	*zha_nan = 19;

	printf("girl : %d wife: %d\n", girl, wife);

	// The second
	int const * zhi_nan = &wife;
	printf("zhi_nan Wife's age: %d\n", *zhi_nan);
	zhi_nan = &girl;
	printf("zhi_nan Girlfriend's age: %d\n", *zhi_nan);

	// the third type
	int * const nuan_nan = &wife;
	*nuan_nan = 26;
	printf("nuan_nan Wife's age: %d\n", wife);

	// A fourth
	const int * const super_nuan_nan = &wife;
	
	return 0;
}

在这里插入图片描述
总结:
看 const 离类型(int)近,还是离指针变量名近,离谁近,就修饰谁,谁就 不能变

指针的算术运算

指针的自增运算

#include <stdio.h>
#include <stdlib.h>

int main() {
	int ages[] = {21, 15, 18, 14, 23, 28, 10};
	int len = sizeof(ages)/sizeof(ages[0]);

	// Methods a
	for (int i = 0; i < len; i++) {
		printf("The age of the %d cadet is: %d\n", i + 1, ages[i]);
	}

	printf("ages address: 0x%p, The address of the first element : 0x%p\n", ages, &ages[0]);

	int *p = ages;
	printf("The first element of the array: %d\n", *p);

	for (int i = 0; i < len; i++) {
		printf("The %d element of the array: %d address: 0x%p\n", i+1,
			*p, p);
		p++;
	}

	printf("======\n");
	char ch[4] = {'a', 'b', 'c', 'd'};
	char *cp = ch;

	for (int i = 0; i < 4; i++) {
		printf("The %d element of the array: %d address: 0x%p\n", i+1,
			*cp, cp);
		cp++;
	}
	
	return 0;
}

运行结果:

在这里插入图片描述
在这里插入图片描述

总结:
p++ 的概念是在 p 当前地址的基础上 ,自增 p 对应类型的大小 p = p+ 1*(sizeof(类型))

指针的自减运算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// as "12345" Reverse into "54321" output

int main() {
	char input[128];
	int len;
	char tmp;

	scanf("%s", input, 128);
	len = strlen(input);

	// Methods a
	/*for (int i = 0; i < len/2; i++) {
		tmp = input[i];
		input[i] = input[len-i-1];
		input[len-i] = tmp;
	}

	for (int i = 0; i < len; i++) {
		printf("%c", input[i]);
	}
	printf("After the reversal: %s\n", input);
	*/

	// The second way
	/* for (int i = 0; i < len; i++) {
		printf("%c", input[len-i-1]);
	}
	printf("\n");
	*/

	// Third way
	char *p = &input[len-1];

	for (int i = 0; i < len; i++) {
		printf("%c", *p);
		p--;
	}
	printf("\n");

	return 0;
}

运行结果:
在这里插入图片描述
指针与整数之间的加减运算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	int ages[] = {20, 18, 19, 24, 23, 28, 30, 38,35, 32};
	int len = sizeof(ages)/sizeof(ages[0]);

	int *p = ages;
	printf("The age of the seventh most beautiful woman: %d\n", *(p+6));
	printf("*p+6 = :  %d\n", *(p+2));

	int *p1 = &ages[4];

	printf("Relative to the age of the fifth beauty, the 1 before her: %d\n", *(p1-1));
	printf("Relative to the age of the fifth beauty, the 3 before her: %d\n", *(p1-3));
	
	return 0;
}

运行结果:
在这里插入图片描述
知识点:
(1)指针与整数的运算,指针加减数字表示的意义是指针在数组中位置的移动; 对于整数部分而言,它代表的是一个元素,对于不同的数据类型,其数组的元素占 用的字节是不一样的,
比如指针 + 1,并不是在指针地址的基础之上加 1 个地址,而是在这个指针地址的 基础上加 1 个元素占用的字节数:
 如果指针的类型是 char*,那么这个时候 1 代表 1 个字节地址;
 如果指针的类型是 int*,那么这个时候 1 代表 4 个字节地址;
 如果指针的类型是 float*,那么这个时候 1 代表 4 个字节地址;
 如果指针的类型是 double*,那么这个时候 1 代表 8 个字节地址。

(3)通用公式:
数据类型 *p;
p + n 实际指向的地址:p 基地址 + n * sizeof(数据类型)
p - n 实际指向的地址:p 基地址 - n * sizeof(数据类型)
比如
(1)对于 int 类型,比如 p 指向 0x0061FF14,则:
p+1 实际指向的是 0x0061FF18,与 p 指向的内存地址相差 4 个字节;
p+2 实际指向的是 0x0061FF1C,与 p 指向的内存地址相差 8 个字节
(2)对于 char 类型,比如 p 指向 0x0061FF28,则:
p+1 实际指向的是 0x0061FF29,与 p 指向的内存地址相差 1 个字节;
p+1 实际指向的是 0x0061FF2A,与 p 指向的内存地址相差 2 个字节;

李连杰的二级指针

二级指针也是一个普通的指针变量,只是它里面保存的值是另外一个一级指针的地址
定义:
int guizi1 = 888; int *guizi2 = &guizi1; //1 级指针,保存 guizi1 的地址 int **liujian = &guizi2; //2 级指针,保存 guizi2 的地址,guizi2 本身是一个一级指针变量

在这里插入图片描述

#include <stdio.h> 
#include <stdlib.h> 
int main(void){ 
	int guizi2 = 888; //存枪的第 2 个柜子 
	int *guizi1 = &guizi2; //存第 2 个柜子地址的第一个柜子 
	int **liujian = &guizi1; //手握第一个柜子地址的刘建 
	
	printf("刘建打开第一个柜子,获得第二个柜子的地址:0x%p\n", *liujian);
	printf("guizi2 的地址:0x%p\n", &guizi2); 	
																     
	int *tmp; 
	tmp = *liujian; printf("访问第二个柜子的地址,拿到枪:%d\n", *tmp); 
	printf("刘建一步到位拿到枪:%d\n", **liujian); //缩写成 **liujian 

	return 0;
}

二级指针的用途:

  1. 普通指针可以将变量通过参数“带入”函数内部,但没办法将内部变量“带出”函数
    在这里插入图片描述
  2. 二级指针可以不但可以将变量通过参数函数内部,也可以将函数内部变量 “带出”到函 数外部。
    在这里插入图片描述
#include <stdio.h>
#include <stdlib.h>

void swap(int *a, int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;

}

void boy_home(int **meipo) {
	static int boy = 23;
	*meipo = &boy;
	
}

int main() {
	int *meipo = NULL;
	boy_home(& meipo);
	printf("boy: %d\n", *meipo);
	
	return 0;
}

运行结果:
在这里插入图片描述

发布了33 篇原创文章 · 获赞 33 · 访问量 243

猜你喜欢

转载自blog.csdn.net/m0_45867846/article/details/105551185