衣带渐宽终不悔,为“指针”消得人憔悴(一)

为什么要使用指针

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

    

指针定义

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

int main(void){ 
	int age; 
	char ch; 
	
	//定义了一个指针 
	//指针本身也是一个变量 
	//名称是 p, 它是一个指针,可以指向一个整数 
	//也就是说: p 的值就是一个整数的地址!!! 
	int *p ; 
	char * c; 
	
	//指针 p 指向了 age 
	//p 的值,就是 age 的地址 
	p = &age; 
	c = &ch; 
	
	//scanf_s("%d", &age); 
	scanf_s("%d", p); 
	
	printf("age: %d\n", age); 
	
	system("pause"); 
	return 0; 
}

/*指针定义方式:
int *p; 或者 int *p1, *p2; (方式一)
int* p; (方式二)
int* p1,p2; (p1 是指针, p2 只是整形变量 )

int * p; 或者int*p;(不建议)
*/

在这里插入图片描述

    

指针的初始化

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

int main(void){ 
int room = 2; 

//定义两个指针变量指向 room 
int *p1 = &room; 
int *p2 = &room; 

printf("room 地址:0x%p\n", &room); 
printf("p1 地址:0x%p\n", &p1); 
printf("p2 地址:0x%p\n", &p2); 

printf("room 所占字节:%d\n", sizeof(room)); 
printf("p1 所占字节:%d\n", sizeof(p1)); 
printf("p2 所占字节:%d\n", sizeof(p2)); 

system("pause");
return 0}
/*注意: 
32 位系统中,int 整数占 4 个字节,指针同样占 4 个字节 
64 位系统中,int 整数占 4 个字节,指针占 8 个字节
*/

在这里插入图片描述

    

指针的访问

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

int main(void){
	int room = 2 ; 
	int * girl = &room; 
	int x = 0; 
	x = *girl;
//*是一个特殊的运算符,*girl表示读取指针girl所指向的变量的值,*girl相当于 room 
	
	printf("x: %d\n", x); 
	*girl = 4; //相当于 room = 4 
	
	printf("room: %d, *girl: %d\n", room, *girl); 
	
	system("pause"); 
	return 0; 
}

在这里插入图片描述

    

空指针和坏指针

什么是空指针?
空指针,就是值为 0 的指针。(任何程序数据都不会存储在地址为 0 的内存块中,它是被操作系 统预留的内存块。)

int *p = 0;
或者
int *p = NULL; //强烈推荐

    
空指针的使用:
(1)指针初始化为空指针
int *select = NULL;
目的就是,避免访问非法数据。

    
(2)指针不再使用时,可以设置为空指针
int *select = &a;
select = NULL;

    
(3)表示这个指针还没有具体的指向,使用前进行合法性判断

 int *p = NULL; 
 // 。。。。 
 if (p) { //p 等同于 p!=NULL 
 //指针不为空,对指针进行操作 
 }

    
坏指针

int *select; //没有初始化 
情形一
printf("选择的房间是: %d\n", *select); //此时select没有初始化,
//*select没有对应值

情形二
select = 100; 
printf("选择的房间是: %d\n", *select);//select赋值100
//*select是地址为100的里面的值,
//但是地址为100和地址为0这样的地址都是被系统预留的内存块无法访问

    

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

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

//const 和指针 
int main(void){ 
	int wife = 24; 
	int girl = 18; 
	
	//第一种 渣男型 
	int * zha_nan = &wife; 
	*zha_nan = 25; 
	zha_nan = &girl; 
	*zha_nan = 19; 
	
	printf("girl : %d wife: %d\n", girl, wife); 
	
	//第二种 直男型 
	//const int * zhi_nan = &wife; //第一种写法 
	int const * zhi_nan = &wife; // 第二种写法 
	//*zhi_nan = 26; 无法对数据进行修改,但是可以换老婆
	printf("直男老婆的年龄:%d\n", *zhi_nan); 
	zhi_nan = &girl; 
	printf("直男女朋友的年龄:%d\n", *zhi_nan); 
	//*zhi_nan = 20; 无法对数据进行修改,但是可以换老婆
	
	//第三种 暖男型 
	int * const nuan_nan = &wife; 
	*nuan_nan = 26; 
	printf("暖男老婆的年龄:%d\n", wife); 
	//nuan_nan = &girl; //可以对数据进行修改,但是为人专一不能换老婆 
	
	//第四种超级暖男型的 
	const int * const super_nuan_nan = &wife; //不允许指向别的地址, 
	//不能修改指向变量的值 
	//*super_nuan_nan = 28; 
	//super_nuan_nan = &girl; 
	system("pause"); 
	return 0; 
}

总结: 看 const 离类型(int)近,还是离指针变量名近,离谁近,就修饰谁,谁就 不能变

    

指针的算术运算

#include <stdio.h> 
#include <stdlib.h> 
int main(void){ 
	int ages[]={21,15,18,14,23,28,10}; 
	int len = sizeof(ages)/sizeof(ages[0]); 
	
	//使用数组的方式来访问数组 
	for( int i=0; i<len; i++){ 
		printf("第%d 个学员的年龄是:%d\n", i+1, ages[i]); 
	}
	
	//打印数组的地址和第一个成员的地址 
	printf("ages 的地址: 0x%p , 第一个元素的地址: 0x%p\n", ages, &ages[0]); 
	int *p = ages; 
	
	//访问第一个元素 
	printf("数组的第一个元素:%d\n", *p);
	
	 //访问第二个元素 //p++; // p = p+ 1*(sizeof(int)) 
	 //printf("数组的第二个元素:%d, 第二个元素的地址: 0x%p\n", *p, p); 
	
	for(int i=0; i<len; i++){ 
		printf("数组的第%d 个元素:%d 地址: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("数组的第%d 个元素:%c 地址:0x%p\n", i+1, *cp, cp); 
	cp++; 
	}
	
	system("pause");
	return 0}

在这里插入图片描述
总结: p++ 的概念是在 p 当前地址的基础上 ,自增 p 对应类型的大小 p = p+ 1x (sizeof(类型))

自减同理、指针与整数的加法、减法同理

    
    指针与整数的运算 ,指针加减数字表示的意义是指针在数组中位置的移动;

     对于整数部分而言,它代表的是一个元素,对于不同的数据类型,其数组的元素占 用的字节是不一样的, 比如指针 + 1,并不是在指针地址的基础之上加 1 个地址,而是在这个指针地址的 基础上加 1 个元素占用的字节数: 
     如果指针的类型是 char*,那么这个时候 1 代表 1 个字节地址; 
     如果指针的类型是 int*,那么这个时候 1 代表 4 个字节地址; 
     如果指针的类型是 float*,那么这个时候 1 代表 4 个字节地址; 
     如果指针的类型是 double*,那么这个时候 1 代表 8 个字节地址。

    
指针与指针之间的加减运算

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

/*** (1)使用“指针-指针”的方式计算整数数组元素的偏移值; * */ 

int main(void){ 
	int ages[] = {20,18,19,24,23,28,30,38, 35, 32}; 
	int ages1[] = {18, 19, 20, 22}; 
	int len = sizeof(ages) / sizeof(ages[0]); 
	int *martin = ages+6; 
	int *rock = ages+9;
	
	printf("rock - martin = %d\n", rock - martin); 
	printf("martin - rock = %d\n", martin - rock); 
	martin = ages+6; 
	rock = ages1+3; 
	
	printf("martin: %p rock: %p rock-martin:%d\n",martin, rock ,rock-martin); 
	
	system("pause"); 
	return 0; 
}

总结:
(1)指针和指针可以做减法操作,但不适合做加法运算;
(2)指针和指针做减法适用的场合:两个指针都指向同一个数组,相减结果为两个指针之 间的元素数目,而不是两个指针之间相差的字节数。
(3)如果两个指针不是指向同一个数组,它们相减就没有意义

发布了26 篇原创文章 · 获赞 3 · 访问量 1539

猜你喜欢

转载自blog.csdn.net/qq_34850023/article/details/104533665